Annotation of coherent/b/bin/c/n0/fold.c, revision 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.