Annotation of coherent/b/bin/c/n0/fold.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * n0/fold.c
                      3:  * Constant expression folder for the C compiler parser.
                      4:  * More of this is done in the code generator.
                      5:  * This one exists only to allow constant expressions in case labels,
                      6:  * in array bounds, and in initializers.
                      7:  */
                      8: 
                      9: #ifdef   vax
                     10: #include "INC$LIB:cc0.h"
                     11: #else
                     12: #include "cc0.h"
                     13: #endif
                     14: 
                     15: extern lval_t  grablval();
                     16: 
                     17: #if    FOLD_DOUBLES
                     18: /*
                     19:  * The double folding code below assumes that the compiler host and target fp
                     20:  * representations are identical,
                     21:  * an assumption the compiler source carefully avoids making everywhere else.
                     22:  * If host fp == target fp,
                     23:  * ordinary C fp operations (+, -, *, / etc.) can be used in folding.
                     24:  * If host fp != target fp, folding requires format translation or emulation.
                     25:  * A compiler produced with this option uses fp,
                     26:  * so in particular the verison of fp it uses must run on all target systems;
                     27:  * e.g., if you compile the compiler -VNDP then the target will need
                     28:  * either an NDP or NDP emulation.
                     29:  */
                     30: extern TREE    *foldd();
                     31: extern double  grabdval();
                     32: #endif
                     33: 
                     34: /*
                     35:  * Try to fold constants.
                     36:  * The given op must be appropriate for folding,
                     37:  * the left subtree must be a constant (ICON/LCON/ZCON/DCON), and
                     38:  * the right subtree (if any) must be a constant (ICON/LCON/ZCON/DCON)
                     39:  * for folding to work.
                     40:  * Return pointer to a constant tree node,
                     41:  * or NULL if folding is impossible.
                     42:  * This code is very casual about lval_t/ulval_t bit equivalence.
                     43:  * Folds double constants if FOLD_DOUBLES.
                     44:  */
                     45: TREE *
                     46: fold0(op, lp, rp) int op; TREE *lp, *rp;
                     47: {
                     48:        register TREE *tp;
                     49:        register lval_t lv, rv;
                     50:        int bool;
                     51:        register int lt, rt, gt, uflag, zflag, lflag;
                     52: 
                     53:        /* Check op dope table to make sure op has a chance of folding. */
                     54:        if ((opdope[op - MIOBASE] & FOLD) == 0)
                     55:                return NULL;
                     56: 
                     57:        /* Check for constant left subtree. */
                     58:        if (!isconst(lp))
                     59:                return NULL;
                     60:        lt = lp->t_type;
                     61: 
                     62:        /* Handle ?: without further ado. */
                     63:        if (op == QUEST) {
                     64:                if (rp->t_op != COLON)
                     65:                        return NULL;            /* parsing must be fubar */
                     66:                return (grablval(lp, 0)) ? rp->t_lp : rp->t_rp;
                     67:        }
                     68: 
                     69:        /* Handle ',' with constant on lhs without further ado. */
                     70:        if (op == COMMA)
                     71:                return rp;
                     72: 
                     73:        if (rp != NULL) {
                     74:                /* Check for constant right subtree. */
                     75:                if (!isconst(rp))
                     76:                        return NULL;
                     77:                rt = rp->t_type;
                     78:        } else
                     79:                rt = lt;                        /* Unary ops: no right subtree */
                     80: 
                     81:        /*
                     82:         * Find the goal type in the conversion dope table.
                     83:         * Watch out for shifts, right type implicitly T_INT.
                     84:         */
                     85:        if (op == SHL || op == SHR)
                     86:                rt = T_INT;
                     87:        gt = cvdope[13 * (lt - T_CHAR) + (rt - T_CHAR)] & GOAL;
                     88: 
                     89:        /* Set unsigned, long, ZCON flags based on goal type. */
                     90:        uflag = (gt == T_UINT || gt == T_ULONG);
                     91:        lflag = (gt == T_LONG || gt == T_ULONG);
                     92:        zflag = (lp->t_op == ZCON || (rp != NULL && rp->t_op == ZCON));
                     93: 
                     94: #if    FOLD_DOUBLES
                     95:        /* Fold as doubles if goal type is double. */
                     96:        if (gt == T_DOUBLE) {
                     97:                if (opdope[op - MIOBASE] & NFLT)
                     98:                        return NULL;            /* op is illegal in any case */
                     99:                return foldd(op, lp, rp);
                    100:        }
                    101: #endif
                    102: 
                    103:        /* Grab the left and right values as [u]lval_t. */
                    104:        lv = grablval(lp, uflag);
                    105:        if (rp != NULL)
                    106:                rv = grablval(rp, uflag);
                    107: 
                    108:        /* Perform the folding, computing result in lv or in bool (0 or 1). */
                    109:        bool = -1;
                    110:        switch (op) {
                    111: 
                    112:        case COM:       lv = ~lv;               break;
                    113:        case NEG:       lv = -lv;               break;
                    114:        case ADD:       lv += rv;               break;
                    115:        case SUB:       lv -= rv;               break;
                    116:        case MUL:       lv *= rv;               break;
                    117:        case AND:       lv &= rv;               break;
                    118:        case OR:        lv |= rv;               break;
                    119:        case XOR:       lv ^= rv;               break;
                    120:        case SHL:       lv <<= rv;              break;
                    121: 
                    122:        /* Ops /, % and >> are different for signed and unsigned cases. */
                    123:        case DIV:
                    124:                if (rv == 0) {
                    125:                        cwarn("divide by zero");
                    126:                        return NULL;
                    127:                }
                    128:                if (uflag)
                    129:                        lv = ((ulval_t)lv / (ulval_t)rv);
                    130:                else
                    131:                        lv /= rv;
                    132:                break;
                    133: 
                    134:        case REM:
                    135:                if (rv == 0) {
                    136:                        cwarn("zero modulus");
                    137:                        return NULL;
                    138:                }
                    139:                if (uflag)
                    140:                        lv = ((ulval_t)lv % (ulval_t)rv);
                    141:                else
                    142:                        lv %= rv;
                    143:                break;
                    144: 
                    145:        case SHR:
                    146:                if (uflag)
                    147:                        lv = ((ulval_t)lv >> (ulval_t)rv);
                    148:                else
                    149:                        lv >>= rv;
                    150:                break;
                    151: 
                    152:        /* Relations and conditionals return T_INT result in bool. */
                    153:        case NOT:       bool = !lv;             break;
                    154:        case EQ:        bool = lv == rv;        break;
                    155:        case NE:        bool = lv != rv;        break;
                    156:        case ANDAND:    bool = (lv && rv);      break;
                    157:        case OROR:      bool = (lv || rv);      break;
                    158:        /* Nonequality relations are different for signed and unsigned cases. */
                    159:        case LT:
                    160:                bool = (uflag) ? ((ulval_t)lv <  (ulval_t)rv) : (lv <  rv);
                    161:                break;
                    162:        case LE:
                    163:                bool = (uflag) ? ((ulval_t)lv <= (ulval_t)rv) : (lv <= rv);
                    164:                break;
                    165:        case GT:
                    166:                bool = (uflag) ? ((ulval_t)lv >  (ulval_t)rv) : (lv >  rv);
                    167:                break;
                    168:        case GE:
                    169:                bool = (uflag) ? ((ulval_t)lv >= (ulval_t)rv) : (lv >= rv);
                    170:                break;
                    171: 
                    172:        default:                /* shouldn't happen if opdope is right */
                    173:                return NULL;
                    174:        }
                    175: 
                    176:        /* Allocate a TREE for the result, store result, return it. */
                    177:        tp = talloc();
                    178:        if (bool != -1) {                       /* boolean result */
                    179:                tp->t_op   = ICON;
                    180:                tp->t_type = T_INT;
                    181:                tp->t_ival = bool;
                    182:        } else if (lflag) {                     /* [u]long result */
                    183:                tp->t_op   = LCON;
                    184:                tp->t_type = (uflag) ? T_ULONG : T_LONG;
                    185:                tp->t_lval = lv;
                    186:        } else if (zflag) {                     /* size_t result */
                    187:                tp->t_op   = ZCON;
                    188:                tp->t_type = T_UINT;
                    189:                tp->t_zval = lv;
                    190:        } else {                                /* [u]int result */
                    191:                tp->t_op   = ICON;
                    192:                tp->t_type = (uflag) ? T_UINT : T_INT;
                    193:                tp->t_ival = lv;
                    194:        }
                    195:        return tp;
                    196: }
                    197: 
                    198: /*
                    199:  * Return true if tp represents a constant (ICON, LCON, ZCON, DCON).
                    200:  */
                    201: int
                    202: isconst(tp) register TREE *tp;
                    203: {
                    204:        register int op;
                    205: 
                    206:        return (tp->t_dp == NULL
                    207:             && ((op = tp->t_op) == ICON
                    208:                 || op == LCON
                    209:                 || op == ZCON
                    210: #if    FOLD_DOUBLES
                    211:                 || op == DCON
                    212: #endif
                    213:                ));
                    214: }
                    215: 
                    216: /*
                    217:  * Grab the value of a constant as an lval_t (or ulval_t, really).
                    218:  * Zero extend if the goal type is unsigned.
                    219:  */
                    220: lval_t
                    221: grablval(tp, uflag) register TREE *tp; int uflag;
                    222: {
                    223:        switch (tp->t_op) {
                    224:        case ICON:
                    225:                return (uflag) ? (ulval_t)(uival_t)tp->t_ival : tp->t_ival;
                    226:        case ZCON:
                    227:                return (ulval_t)tp->t_zval;
                    228:        case LCON:
                    229:                return tp->t_lval;
                    230: #if    FOLD_DOUBLES
                    231:        case DCON:
                    232:                return dval_to_d(tp);
                    233: #endif
                    234:        }
                    235:        cbotch("grablval");
                    236: }
                    237: 
                    238: #if    FOLD_DOUBLES
                    239: 
                    240: /*
                    241:  * Fold double constants.
                    242:  */
                    243: TREE *
                    244: foldd(op, lp, rp) int op; TREE *lp, *rp;
                    245: {
                    246:        register TREE *tp;
                    247:        int bool;
                    248:        double lv, rv;
                    249: 
                    250:        lv = grabdval(lp);
                    251:        if (rp != NULL)
                    252:                rv = grabdval(rp);
                    253:  
                    254: 
                    255:        /* Perform the folding, leaving result in lv or in bool (0 or 1). */
                    256:        bool = -1;
                    257:        switch(op) {
                    258: 
                    259:        case NEG:       lv = -lv;               break;
                    260:        case ADD:       lv += rv;               break;
                    261:        case SUB:       lv -= rv;               break;
                    262:        case MUL:       lv *= rv;               break;
                    263:        case DIV:       lv /= rv;               break;
                    264: 
                    265:        /* Relations and conditionals return T_INT result in bool. */
                    266:        case NOT:       bool = !lv;             break;
                    267:        case EQ:        bool = lv == rv;        break;
                    268:        case NE:        bool = lv != rv;        break;
                    269:        case LT:        bool = lv <  rv;        break;
                    270:        case LE:        bool = lv <= rv;        break;
                    271:        case GT:        bool = lv >  rv;        break;
                    272:        case GE:        bool = lv >= rv;        break;
                    273:        case ANDAND:    bool = (lv && rv);      break;
                    274:        case OROR:      bool = (lv || rv);      break;
                    275: 
                    276:        default:                /* shouldn't happen if opdope is right */
                    277:                return NULL;
                    278:        }
                    279: 
                    280:        /* Allocate a TREE for the result and store the result. */
                    281:        tp = talloc();
                    282:        if (bool != -1) {                       /* boolean result */
                    283:                tp->t_op  = ICON;
                    284:                tp->t_type = T_INT;
                    285:                tp->t_ival = bool;
                    286:        } else {                                /* double result */
                    287:                tp->t_op  = DCON;
                    288:                tp->t_type = T_DOUBLE;
                    289:                d_to_dval(tp, lv);
                    290:        }
                    291:        return tp;
                    292: }
                    293: 
                    294: /*
                    295:  * Grab the value of a constant as a double.
                    296:  */
                    297: double
                    298: grabdval(tp) register TREE *tp;
                    299: {
                    300:        register int t;
                    301: 
                    302:        switch (tp->t_op) {
                    303:        case ICON:
                    304:                return ((t = tp->t_type) == T_UINT || t == T_ULONG)
                    305:                                ? (uival_t)tp->t_ival : tp->t_ival;
                    306:        case ZCON:
                    307:                return (uival_t)tp->t_zval;
                    308:        case LCON:
                    309:                return ((t = tp->t_type) == T_UINT || t == T_ULONG)
                    310:                                ? (ulval_t)tp->t_lval : tp->t_lval;
                    311:        case DCON:
                    312:                return dval_to_d(tp);
                    313:        }
                    314:        cbotch("grabdval");
                    315: }
                    316: 
                    317: #endif
                    318: 
                    319: /* end of n0/fold.c */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.