123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465 |
- /* $Header$ */
- /* A R I T H M E T I C C O N V E R S I O N S */
- /* This file contains the routines for the various conversions that
- may befall operands in C. It is structurally a mess, but I haven't
- decided yet whether I can't find the right structure or the
- semantics of C is a mess.
- */
- #include "botch_free.h"
- #include "nobitfield.h"
- #include "alloc.h"
- #include "idf.h"
- #include "arith.h"
- #include "type.h"
- #include "label.h"
- #include "expr.h"
- #include "Lpars.h"
- #include "storage.h"
- #include "field.h"
- #include "mes.h"
- extern char *symbol2str();
- extern char options[];
- int
- arithbalance(e1p, oper, e2p) /* RM 6.6 */
- struct expr **e1p, **e2p;
- {
- /* The expressions *e1p and *e2p are balanced to be operands
- of the arithmetic operator oper.
- */
- register int t1, t2, u1, u2;
- t1 = any2arith(e1p, oper);
- t2 = any2arith(e2p, oper);
- /* Now t1 and t2 are either INT or LONG or DOUBLE */
- if (t1 == DOUBLE && t2 != DOUBLE)
- t2 = int2float(e2p, double_type);
- else
- if (t2 == DOUBLE && t1 != DOUBLE)
- t1 = int2float(e1p, double_type);
- else
- if (t1 == DOUBLE)
- return DOUBLE;
- /* Now they are INT or LONG */
- u1 = (*e1p)->ex_type->tp_unsigned;
- u2 = (*e2p)->ex_type->tp_unsigned;
- /* if either is long, the other will be */
- if (t1 == LONG && t2 != LONG)
- t2 = int2int(e2p, u2 ? ulong_type : long_type);
- else
- if (t2 == LONG && t1 != LONG)
- t1 = int2int(e1p, u1 ? ulong_type : long_type);
- /* if either is unsigned, the other will be */
- if (u1 && !u2)
- t2 = int2int(e2p, (t1 == LONG) ? ulong_type : uint_type);
- else
- if (!u1 && u2)
- t1 = int2int(e1p, (t2 == LONG) ? ulong_type : uint_type);
- return t1;
- }
- relbalance(e1p, oper, e2p)
- register struct expr **e1p, **e2p;
- {
- /* The expressions *e1p and *e2p are balanced to be operands
- of the relational operator oper.
- */
- if ((*e1p)->ex_type->tp_fund == FUNCTION)
- function2pointer(e1p);
- if ((*e2p)->ex_type->tp_fund == FUNCTION)
- function2pointer(e2p);
- if ((*e1p)->ex_type->tp_fund == POINTER)
- ch76pointer(e2p, oper, (*e1p)->ex_type);
- else
- if ((*e2p)->ex_type->tp_fund == POINTER)
- ch76pointer(e1p, oper, (*e2p)->ex_type);
- else
- if ( (*e1p)->ex_type == (*e2p)->ex_type &&
- (*e1p)->ex_type->tp_fund == ENUM
- )
- {}
- else
- arithbalance(e1p, oper, e2p);
- }
- ch76pointer(expp, oper, tp)
- register struct expr **expp;
- register struct type *tp;
- {
- /* Checks whether *expp may be compared to tp using oper,
- as described in chapter 7.6 and 7.7.
- tp is known to be a pointer.
- */
- if ((*expp)->ex_type->tp_fund == POINTER) {
- if ((*expp)->ex_type != tp)
- ch7cast(expp, oper, tp);
- }
- else
- if ( is_integral_type((*expp)->ex_type) &&
- ( !options['R'] /* we don't care */ ||
- (oper == EQUAL || oper == NOTEQUAL || oper == ':')
- )
- ) /* ch 7.7 */
- ch7cast(expp, CAST, tp);
- else {
- if ((*expp)->ex_type != error_type)
- error("%s on %s and pointer",
- symbol2str(oper),
- symbol2str((*expp)->ex_type->tp_fund)
- );
- (*expp)->ex_type = error_type;
- ch7cast(expp, oper, tp);
- }
- }
- int
- any2arith(expp, oper)
- register struct expr **expp;
- {
- /* Turns any expression into int_type, long_type or
- double_type.
- */
- int fund = (*expp)->ex_type->tp_fund;
- switch (fund) {
- case CHAR:
- case SHORT:
- int2int(expp,
- (*expp)->ex_type->tp_unsigned ? uint_type : int_type);
- break;
- case INT:
- case LONG:
- break;
- case ENUM:
- if ( is_test_op(oper) || oper == '=' || oper == PARCOMMA ||
- oper == ',' || oper == ':' ||
- ( !options['R'] &&
- (is_arith_op(oper) || is_asgn_op(oper))
- )
- )
- {}
- else
- warning("%s on enum", symbol2str(oper));
- int2int(expp, int_type);
- break;
- case FLOAT:
- float2float(expp, double_type);
- break;
- case DOUBLE:
- break;
- #ifndef NOBITFIELD
- case FIELD:
- field2arith(expp);
- break;
- #endif NOBITFIELD
- default:
- error("operator %s on non-numerical operand (%s)",
- symbol2str(oper), symbol2str(fund));
- case ERRONEOUS:
- free_expression(*expp);
- *expp = intexpr((arith)1, INT);
- break;
- }
- return (*expp)->ex_type->tp_fund;
- }
- struct expr *
- arith2arith(tp, oper, expr)
- struct type *tp;
- int oper;
- struct expr *expr;
- {
- /* arith2arith constructs a new expression containing a
- run-time conversion between some arithmetic types.
- */
- register struct expr *new = new_expr();
-
- clear((char *)new, sizeof(struct expr));
- new->ex_file = expr->ex_file;
- new->ex_line = expr->ex_line;
- new->ex_type = tp;
- new->ex_class = Type;
- return new_oper(tp, new, oper, expr);
- }
- int
- int2int(expp, tp)
- register struct expr **expp;
- struct type *tp;
- {
- /* The expression *expp, which is of some integral type, is
- converted to the integral type tp.
- */
-
- if (is_cp_cst(*expp)) {
- (*expp)->ex_type = tp;
- cut_size(*expp);
- }
- else {
- *expp = arith2arith(tp, INT2INT, *expp);
- }
- return (*expp)->ex_type->tp_fund;
- }
- int
- int2float(expp, tp)
- struct expr **expp;
- struct type *tp;
- {
- /* The expression *expp, which is of some integral type, is
- converted to the floating type tp.
- */
-
- fp_used = 1;
- *expp = arith2arith(tp, INT2FLOAT, *expp);
- return (*expp)->ex_type->tp_fund;
- }
- float2int(expp, tp)
- struct expr **expp;
- struct type *tp;
- {
- /* The expression *expp, which is of some floating type, is
- converted to the integral type tp.
- */
-
- fp_used = 1;
- *expp = arith2arith(tp, FLOAT2INT, *expp);
- }
- float2float(expp, tp)
- struct expr **expp;
- struct type *tp;
- {
- /* The expression *expp, which is of some floating type, is
- converted to the floating type tp.
- There is no need for an explicit conversion operator
- if the expression is a constant.
- */
-
- fp_used = 1;
- if ((*expp)->ex_class == Float) {
- (*expp)->ex_type = tp;
- }
- else {
- *expp = arith2arith(tp, FLOAT2FLOAT, *expp);
- }
- }
- array2pointer(expp)
- struct expr **expp;
- {
- /* The expression, which must be an array, it is converted
- to a pointer.
- */
- (*expp)->ex_type =
- construct_type(POINTER, (*expp)->ex_type->tp_up, (arith)0);
- }
- function2pointer(expp)
- struct expr **expp;
- {
- /* The expression, which must be a function, it is converted
- to a pointer to the function.
- */
- (*expp)->ex_type =
- construct_type(POINTER, (*expp)->ex_type, (arith)0);
- }
- opnd2integral(expp, oper)
- struct expr **expp;
- int oper;
- {
- register int fund = (*expp)->ex_type->tp_fund;
- if (fund != INT && fund != LONG) {
- if (fund != ERRONEOUS)
- error("%s operand to %s",
- symbol2str(fund), symbol2str(oper));
- *expp = intexpr((arith)1, INT);
- /* fund = INT; */
- }
- }
- opnd2logical(expp, oper)
- struct expr **expp;
- int oper;
- {
- register int fund;
- if ((*expp)->ex_type->tp_fund == FUNCTION)
- function2pointer(expp);
- #ifndef NOBITFIELD
- else
- if ((*expp)->ex_type->tp_fund == FIELD)
- field2arith(expp);
- #endif NOBITFIELD
- fund = (*expp)->ex_type->tp_fund;
- switch (fund) {
- case CHAR:
- case SHORT:
- case INT:
- case LONG:
- case ENUM:
- case POINTER:
- case FLOAT:
- case DOUBLE:
- break;
- default:
- error("%s operand to %s",
- symbol2str(fund), symbol2str(oper));
- case ERRONEOUS:
- *expp = intexpr((arith)1, INT);
- break;
- }
- }
- opnd2test(expp, oper)
- struct expr **expp;
- {
- opnd2logical(expp, oper);
- if ((*expp)->ex_class == Oper && is_test_op((*expp)->OP_OPER))
- { /* It is already a test */ }
- else
- ch7bin(expp, NOTEQUAL, intexpr((arith)0, INT));
- }
- int
- is_test_op(oper)
- {
- switch (oper) {
- case '<':
- case '>':
- case LESSEQ:
- case GREATEREQ:
- case EQUAL:
- case NOTEQUAL:
- case '!':
- case AND:
- case OR: /* && and || also impose a test */
- return 1;
- default:
- return 0;
- }
- /*NOTREACHED*/
- }
- int
- is_arith_op(oper)
- {
- switch (oper) {
- case '*':
- case '/':
- case '%':
- case '+':
- case '-':
- case LEFT:
- case RIGHT:
- case '&':
- case '^':
- case '|':
- return 1;
- default:
- return 0;
- }
- }
- int
- is_asgn_op(oper)
- {
- switch (oper) {
- case '=':
- case PLUSAB:
- case MINAB:
- case TIMESAB:
- case DIVAB:
- case MODAB:
- case LEFTAB:
- case RIGHTAB:
- case ANDAB:
- case ORAB:
- case XORAB:
- return 1;
- default:
- return 0;
- }
- }
- any2opnd(expp, oper)
- struct expr **expp;
- {
- if (!*expp)
- return;
- switch ((*expp)->ex_type->tp_fund) { /* RM 7.1 */
- case CHAR:
- case SHORT:
- case ENUM:
- case FLOAT:
- any2arith(expp, oper);
- break;
- case ARRAY:
- array2pointer(expp);
- break;
- #ifndef NOBITFIELD
- case FIELD:
- field2arith(expp);
- break;
- #endif NOBITFIELD
- }
- }
- #ifndef NOBITFIELD
- field2arith(expp)
- struct expr **expp;
- {
- /* The expression to extract the bitfield value from the
- memory word is put in the tree.
- */
- register struct type *tp = (*expp)->ex_type->tp_up;
- register struct field *fd = (*expp)->ex_type->tp_field;
- register struct type *atype = tp->tp_unsigned ? uword_type : word_type;
- (*expp)->ex_type = atype;
- if (atype->tp_unsigned) { /* don't worry about the sign bit */
- ch7bin(expp, RIGHT, intexpr((arith)fd->fd_shift, INT));
- ch7bin(expp, '&', intexpr(fd->fd_mask, INT));
- }
- else { /* take care of the sign bit: sign extend if needed */
- register arith bits_in_type = atype->tp_size * 8;
- ch7bin(expp, LEFT,
- intexpr(bits_in_type - fd->fd_width - fd->fd_shift, INT)
- );
- ch7bin(expp, RIGHT, intexpr(bits_in_type - fd->fd_width, INT));
- }
- ch7cast(expp, CAST, tp); /* restore its original type */
- }
- #endif NOBITFIELD
- /* switch_sign_fp() negates the given floating constant expression
- The lexical analyser has reserved an extra byte of space in front
- of the string containing the representation of the floating
- constant. This byte contains the '-' character and we have to
- take care of the first byte the fl_value pointer points to.
- */
- switch_sign_fp(expr)
- struct expr *expr;
- {
- if (*(expr->FL_VALUE) == '-')
- ++(expr->FL_VALUE);
- else
- --(expr->FL_VALUE);
- }
|