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

1.1       root        1: /*
                      2:  * n0/i386/bind.c
                      3:  * Machine-specific parts of the C compiler parser.
                      4:  * i386.
                      5:  */
                      6: 
                      7: #ifdef   vax
                      8: #include "INC$LIB:cc0.h"
                      9: #else
                     10: #include "cc0.h"
                     11: #endif
                     12: 
                     13: /* Local stack: local offset and register mask. */
                     14: typedef        struct  locals  {
                     15:        struct  locals *l_lstp;
                     16:        ival_t  l_lofs;
                     17:        int     l_mask;
                     18: }      LOCALS;
                     19: 
                     20: LOCALS *clstp;                 /* Local stack                  */
                     21: ival_t clofs;                  /* Current local offset         */
                     22: int    cmask;                  /* Current mask                 */
                     23: ival_t llofs;                  /* Last local offset reported   */
                     24: int    lmask;                  /* Last register mask reported  */
                     25: int    alignment;              /* Alignment from #pragma       */
                     26: 
                     27: /*
                     28:  * This table is indexed by C type to obtain the size
                     29:  * in bytes of a machine object.
                     30:  */
                     31: int     mysizes[] = {
                     32:        0,                      /* T_NONE               */
                     33:        1,      1,              /* T_CHAR    T_UCHAR    */
                     34:        2,      2,              /* T_SHORT   T_USHORT   */
                     35:        4,      4,              /* T_INT     T_UINT     */
                     36:        4,                      /* T_PTR                */
                     37:        4,      4,              /* T_LONG    T_ULONG    */
                     38:        4,      8,              /* T_FLOAT   T_DOUBLE   */
                     39:        0,                      /* T_VOID               */
                     40:        0,      0,              /* T_STRUCT  T_FSTRUCT  */
                     41:        0,      0,              /* T_UNION   T_FUNION   */
                     42:        0,      0               /* T_ENUM    T_FENUM    */
                     43: };
                     44: 
                     45: /*
                     46:  * This table is indexed by C type to obtain the machine type,
                     47:  * as defined in 'mch.h'.
                     48:  */
                     49: char    mytypes[] = {
                     50:        0,                      /* T_NONE               */
                     51:        S8,     U8,             /* T_CHAR    T_UCHAR    */
                     52:        S16,    U16,            /* T_SHORT   T_USHORT   */
                     53:        S32,    U32,            /* T_INT     T_UINT     */
                     54:        PTR,                    /* T_PTR                */
                     55:        S32,    U32,            /* T_LONG    T_ULONG    */
                     56:        F32,    F64,            /* T_FLOAT   T_DOUBLE   */
                     57:        S32,                    /* T_VOID               */
                     58:        BLK,    0,              /* T_STRUCT  T_FSTRUCT  */
                     59:        BLK,    0,              /* T_UNION   T_FUNION   */
                     60:        0,      0               /* T_ENUM    T_FENUM    */
                     61: };
                     62: 
                     63: /*
                     64:  * main() calls this routine to perform machine-dependent parser setup.
                     65:  */
                     66: vinit()
                     67: {
                     68: #if    MONOLITHIC
                     69:        alignment = 0;
                     70: #endif
                     71: }
                     72: 
                     73: /*
                     74:  * Empty the local binding stack and mark the unavailable registers.
                     75:  */
                     76: initlocals()
                     77: {
                     78:        clstp = NULL;
                     79:        llofs = clofs = 0;
                     80:        lmask = cmask = BESP|BEBP;
                     81:        bput(AUTOS);
                     82:        iput(clofs);
                     83:        iput((ival_t)cmask);
                     84: }
                     85: 
                     86: /*
                     87:  * Save the current state of the local bindings.
                     88:  */
                     89: savelocals()
                     90: {
                     91:        register LOCALS *lstp;
                     92: 
                     93:        lstp = (LOCALS *) new(sizeof(LOCALS));
                     94:        lstp->l_lstp = clstp;
                     95:        lstp->l_lofs = clofs;
                     96:        lstp->l_mask = cmask;
                     97:        clstp = lstp;
                     98: }
                     99: 
                    100: /*
                    101:  * Restore locals.
                    102:  * Tell the code generator if it changes.
                    103:  */
                    104: restlocals()
                    105: {
                    106:        register LOCALS *lstp;
                    107: 
                    108:        if ((lstp=clstp) == NULL)
                    109:                cbotch("restlocals");
                    110:        clstp = lstp->l_lstp;
                    111:        clofs = lstp->l_lofs;
                    112:        cmask = lstp->l_mask;
                    113:        putautos();
                    114:        free((char *) lstp);
                    115: }
                    116: 
                    117: /*
                    118:  * Inform the code generator (and perhaps the optimizer)
                    119:  * about the current automatic variable allocation.
                    120:  */
                    121: putautos()
                    122: {
                    123:        if (clofs != llofs || cmask != lmask) {
                    124:                llofs = clofs;
                    125:                lmask = cmask;
                    126:                bput(AUTOS);
                    127:                iput(-clofs);
                    128:                iput((ival_t)cmask);
                    129:        }
                    130: }
                    131: 
                    132: /*
                    133:  * Bind locals to the correct place on the stack frame.
                    134:  * Locals grow down from EBP, e.g. EBP-4, EBP-8, etc.
                    135:  */
                    136: bindlocal(sp) register SYM *sp;
                    137: {
                    138:        register int c, regno;
                    139: 
                    140:        if ((c = sp->s_class) == C_REG) {
                    141:                if ((regno = grabreg(sp)) >= 0) {
                    142:                        sp->s_value = regno;
                    143:                        return;
                    144:                }
                    145:                /* Demote register local to auto. */
                    146:                setclass(sp, C_AUTO);
                    147:        }
                    148:        if (c==C_AUTO || c==C_REG) {
                    149:                clofs -= ssize(sp);
                    150:                /* Keep stack dword-aligned. */
                    151:                if ((clofs & 3) != 0)
                    152:                        clofs &= ~3;
                    153:                sp->s_value = clofs;
                    154:                if (clofs >= 0)
                    155:                        cerror("auto \"%s\" is not addressable", sp->s_id);
                    156:        }
                    157: }
                    158: 
                    159: /*
                    160:  * Attempt to get a register for symbol 'sp'.
                    161:  * Only integer dword objects go in registers currently.
                    162:  * Chars, shorts and floats could go in registers if loadreg() were changed.
                    163:  * Return register id if successful, -1 otherwise.
                    164:  */
                    165: grabreg(sp) register SYM *sp;
                    166: {
                    167:        register DIM *dp;
                    168:        register int type;
                    169: 
                    170:        if ((dp = sp->s_dp) != NULL)
                    171:                return (dp->d_type == D_PTR) ? allocreg() : -1;
                    172:        type = sp->s_type;
                    173:        if (type >= T_INT && type <= T_ULONG)
                    174:                return allocreg();
                    175:        return -1;
                    176: }
                    177: /*
                    178:  * Allocate a register.
                    179:  * Currently allocates EBX, ESI and EDI.
                    180:  * Return register id if successful, -1 otherwise.
                    181:  */
                    182: int
                    183: allocreg()
                    184: {
                    185:        if ((cmask&BEBX) == 0) {
                    186:                cmask |= BEBX;
                    187:                return EBX;
                    188:        } else if ((cmask&BESI) == 0) {
                    189:                cmask |= BESI;
                    190:                return ESI;
                    191:        } else if ((cmask&BEDI) == 0) {
                    192:                cmask |= BEDI;
                    193:                return EDI;
                    194:        } else
                    195:                return -1;
                    196: }
                    197: 
                    198: /*
                    199:  * Bind arguments.
                    200:  * Stack frame during function execution:
                    201:  *             ...
                    202:  *     ebp+8   arg1
                    203:  *     ebp+4   return address
                    204:  *     ebp     saved ebp
                    205:  *     ebp-4   auto1
                    206:  *             ...
                    207:        ebp-n   autolast
                    208:  *     ebp-n-4 saved esi       [if required]
                    209:  *     ebp-n-8 saved edi       [if required]
                    210:  *     ebp-n-12 saved ebx      [if required]
                    211:  */
                    212: bindargs()
                    213: {
                    214:        register SYM *sp;
                    215:        register int i;
                    216:        register ival_t offset;
                    217: 
                    218:        offset = 8;                             /* arg1 offset */
                    219:        for (i = 0; i < nargs; ++i) {
                    220:                sp = args[i];
                    221:                if (sp->s_class != C_PREG)
                    222:                        sp->s_class = C_PAUTO;
                    223:                sp->s_value = offset;
                    224:                offset += ssize(sp);
                    225:                /* Keep parameters dword-aligned. */
                    226:                if ((offset & 3) != 0)
                    227:                        offset = (offset + 3) & ~3;
                    228:        }
                    229: }
                    230: 
                    231: /*
                    232:  * Copy register arguments from the stack into the register.
                    233:  * Change class of the argument to plain register.
                    234:  * Note that bindargs() has put the stack displacement
                    235:  * into the 's_value' field of the argument symbol.
                    236:  */
                    237: loadargs()
                    238: {
                    239:        register SYM *sp;
                    240:        register int i, r;
                    241:        register ival_t v;
                    242: 
                    243:        for (i = 0; i < nargs; ++i) {
                    244:                sp = args[i];
                    245:                if (sp->s_class == C_PREG) {
                    246:                        if ((r=grabreg(sp)) >= 0) {
                    247:                                v = sp->s_value;        /* stack offset */
                    248:                                sp->s_class = C_REG;
                    249:                                sp->s_value = r;        /* register number */
                    250:                                loadreg(sp, v);
                    251:                                continue;
                    252:                        }
                    253:                        /* Demote parametric register to parametric auto. */
                    254:                        setclass(sp, C_PAUTO);
                    255:                }
                    256:        }
                    257: }
                    258: 
                    259: /*
                    260:  * Change the storage class of sp.
                    261:  * Issue a 'strict' warning if desired.
                    262:  */
                    263: setclass(sp, c) register SYM *sp; int c;
                    264: {
                    265:        sp->s_class = c;
                    266:        if (isvariant(VSNREG))
                    267:                cstrict("identifier \"%s\" not bound to register", sp->s_id);
                    268: }
                    269: 
                    270: /*
                    271:  * Load symbol 'sp' from offset 'offset' in the frame.
                    272:  * Since register variables are always dwords,
                    273:  * the type can always be setup to T_INT.
                    274:  */
                    275: loadreg(sp, offset) SYM *sp; ival_t offset;
                    276: {
                    277:        register TREE   *lp, *rp, *tp;
                    278: 
                    279:        newtree(sizeof(TREE));
                    280:        lp = talloc();
                    281:        lp->t_op = REG;
                    282:        lp->t_type = T_INT;
                    283:        lp->t_reg = sp->s_value;
                    284:        rp = talloc();
                    285:        rp->t_op = PID;
                    286:        rp->t_type = T_INT;
                    287:        rp->t_offs = offset;
                    288:        tp = build(ASSIGN, lp, rp);
                    289:        putautos();
                    290:        tput(EEXPR, 0, tp);
                    291: }
                    292: 
                    293: /*
                    294:  * Process a #pragma.
                    295:  * Currently recognizes only "#pragma align [n]".
                    296:  * Return 1 if recognized, 0 if not.
                    297:  */
                    298: pragma(p) char *p;
                    299: {
                    300:        static char align[] = "align";
                    301: 
                    302:        while (*p == ' ' || *p == '\t')
                    303:                ++p;
                    304:        if (strncmp(align, p, sizeof(align)-1) == 0) {
                    305:                alignment = atoi(p + sizeof(align)-1);
                    306:                if (alignment < 0) {
                    307:                        cerror("#pragma align: bad alignment %d", alignment);
                    308:                        alignment = 0;
                    309:                }
                    310:                return 1;
                    311:        }
                    312:        return 0;
                    313: }
                    314: 
                    315: /*
                    316:  * Look at type 't', DIM list 'dp' and field width 'w' (0 for non fields)
                    317:  * and return the bit offset of the base of the structure member.
                    318:  * The 'offset' argument is the current bit offset in the structure or union.
                    319:  * Check for fields that are too wide, bad field base types, and arrange
                    320:  * that the byte, word or dword that spans the field can be grabbed in one grab.
                    321:  * See comments in bindlocal() above concerning reals and bitfield alignment.
                    322:  */
                    323: long
                    324: fieldalign(t, dp, ip, w, offset)
                    325: register DIM   *dp;
                    326: INFO           *ip;
                    327: register int   w;
                    328: long           offset;
                    329: {
                    330:        register long bitwidth, amask, a;
                    331: 
                    332:        /*
                    333:         * Find bit width of type t;
                    334:         * e.g. 8 for char, 16 for short, 32 for int or ptr.
                    335:         */
                    336:        if (dp != NULL) {
                    337:                switch(dp->d_type) {
                    338:                case D_FUNC:    t = T_PTR;      break;
                    339:                case D_PTR:     t = T_PTR;      break;
                    340:                case D_ARRAY:                   break;
                    341:                case D_MOSAR:                   break;
                    342:                default:        cbotch("fieldalign %d", dp->d_type);
                    343:                }
                    344:        } else if (t == T_FENUM)
                    345:                t = T_INT;
                    346:        else if (t == T_ENUM)
                    347:                t = ip->i_type;
                    348:        if (alignment == 0) {
                    349:                if (t == T_STRUCT || t == T_UNION)
                    350:                        bitwidth = 8 * saligntype(ip);
                    351:                else
                    352:                        bitwidth = 8 * mysizes[t];
                    353:                if (bitwidth == 0)
                    354:                        bitwidth = 32;
                    355:                amask = bitwidth - 1;
                    356:        } else {
                    357:                if (t == T_STRUCT || t == T_UNION)
                    358:                        a = saligntype(ip);
                    359:                else
                    360:                        a = (mysizes[t] == 0) ? 4 : mysizes[t];
                    361:                amask = 8 * ((a < alignment) ? a : alignment) - 1;
                    362:                bitwidth = 8 * a;
                    363:        }
                    364:        if (w != 0) {
                    365:                /* Nonzero width bitfield. */
                    366:                if (dp != NULL)
                    367:                        cerror("non scalar field");
                    368:                if (bitwidth > 32)
                    369:                        cerror("bad base type for field");
                    370: #if    0
                    371:                if (w > bitwidth)
                    372:                        cerror("field too wide");
                    373: #endif
                    374:                /* Bump to next alignment boundary if necessary. */
                    375:                if ((offset & amask) + w > bitwidth)
                    376:                        offset = (offset + amask) & ~amask;
                    377:        } else {
                    378:                /* Zero width bitfield or non field. */
                    379:                offset = (offset + amask) & ~amask;
                    380:        }
                    381:        return offset;
                    382: }
                    383: 
                    384: /*
                    385:  * Convert a tree into its low level form.
                    386:  * Fill in the machine type byte looking at the C type
                    387:  * and the segment information.
                    388:  */
                    389: TREE *
                    390: transform(tp, why, above) register TREE *tp; int why, above;
                    391: {
                    392:        register TREE *lp;
                    393:        register int t;
                    394:        register int wd;
                    395: 
                    396:        /*
                    397:         * The way that this code looks at the DIM lists to decide
                    398:         * what type of conversion is inserted makes me sick.
                    399:         * The correct type of conversion node (MUL, DIV, etc.)
                    400:         * should really be inserted when the tree is constructed,
                    401:         * guided by a table.
                    402:         */
                    403:        if (tp->t_op == CONVERT) {
                    404:                lp = tp->t_lp;
                    405:                if (tp->t_dp!=NULL && lp->t_dp==NULL && why!=REXPR) {
                    406:                        tp->t_op = MUL;
                    407:                        tp->t_dp = NULL;
                    408:                        if (lp->t_type != T_INT)
                    409:                                tp->t_lp = bconvert(lp, T_INT, NULL,NULL,NULL);
                    410:                        tp->t_type = T_INT;
                    411:                } else if (tp->t_dp==NULL && lp->t_dp!=NULL && tp->t_rp!=NULL) {
                    412:                        tp->t_op = DIV;
                    413:                        lp->t_dp = NULL;
                    414:                        lp->t_type = T_INT;
                    415:                }
                    416:        }
                    417: 
                    418:        /* Fixup any remaining ZCONs. */
                    419:        if (tp->t_op == ZCON) {
                    420:                tp->t_op = ICON;
                    421:                tp->t_type = T_INT;
                    422:                tp->t_ival = tp->t_zval;
                    423:        }
                    424: 
                    425:        /* Set the type field. */
                    426:        if (tp->t_dp != NULL)
                    427:                tp->t_type = mytypes[T_PTR];
                    428:        else if ((t=tp->t_type)==T_FSTRUCT || t==T_FUNION || t==T_FENUM) {
                    429:                unksize(t, tp->t_ip);
                    430:                tp->t_type = S32;               /* default to S32 */
                    431:        } else {
                    432:                if (t == T_ENUM)
                    433:                        t = tp->t_ip->i_type;   /* enum base type */
                    434:                tp->t_type = mytypes[t];
                    435:        }
                    436: 
                    437:        if (tp->t_op >= MIOBASE) {
                    438:                wd = why;
                    439:                if (why == REXPR)
                    440:                        wd = EEXPR;
                    441:                tp->t_lp = transform(tp->t_lp, wd, tp->t_op);
                    442:                if (tp->t_op!=FIELD && tp->t_rp!=NULL)
                    443:                        tp->t_rp = transform(tp->t_rp, wd, -1);
                    444:                if (tp->t_op==CONVERT && tp->t_rp==NULL) {
                    445:                        lp = tp->t_lp;
                    446:                        if (tp->t_type == lp->t_type)
                    447:                                tp = lp;
                    448:                }
                    449:        }
                    450:        return tp;
                    451: }
                    452: 
                    453: /*
                    454:  * Check if the operator 'op' applied to C types 'lt' and 'rt'
                    455:  * (which are outputs from tltype(), which means that all pointers
                    456:  * have been converted to type T_PTR) involves no conversions.
                    457:  * This means the code generator must deal with the type mismatch.
                    458:  */
                    459: noconvert(op, lt, rt) register int op, lt, rt;
                    460: {
                    461:        if (op==ASSIGN || op==CAST || (op>=EQ && op<=ULT)) {
                    462:                if ((lt>=T_CHAR && lt<=T_UCHAR)
                    463:                &&  (rt>=T_CHAR && rt<=T_UCHAR))
                    464:                        return 1;               /* 8-bit types */
                    465:                if ((lt>=T_SHORT && lt<=T_USHORT)       
                    466:                &&  (rt>=T_SHORT && rt<=T_USHORT))
                    467:                        return 1;               /* 16-bit types */
                    468:                if ((lt>=T_INT  && lt<=T_ULONG)
                    469:                &&  (rt>=T_INT  && rt<=T_ULONG))
                    470:                        return 1;               /* 32-bit types */
                    471:                if (op==CAST && lt==T_FLOAT && rt==T_DOUBLE)
                    472:                        return 1;               /* (float)double */
                    473:        }
                    474:        return 0;
                    475: }
                    476: 
                    477: /*
                    478:  * Align the location counter well enough for the object 'sp'.
                    479:  */
                    480: align(sp) SYM *sp;
                    481: {
                    482:        bput(ALIGN);
                    483:        bput(aligntype(sp));
                    484: }
                    485: 
                    486: /*
                    487:  * Return the appropriate alignment type for 'sp'.
                    488:  * The alignment type is 1 for byte, 2 for word, 4 for dword.
                    489:  */
                    490: aligntype(sp) SYM *sp;
                    491: {
                    492:        register int type, atype, dtype;
                    493:        register DIM *dp;
                    494: 
                    495:        if (alignment != 0)
                    496:                return alignment;       /* use #pragma-defined alignment */
                    497:        type = sp->s_type;
                    498:        atype = mysizes[type];
                    499:        if ((dp = sp->s_dp) != NULL) {
                    500:                while (dp != NULL
                    501:                    && ((dtype = dp->d_type) == D_ARRAY || dtype == D_MOSAR))
                    502:                        dp = dp->d_dp;
                    503:                if (dtype == D_PTR || dtype == D_FUNC)
                    504:                        return 4;       /* pointer to, function returning */
                    505:        }
                    506:        if (atype == 1 || atype == 2 || (atype == 4 && type != T_PTR))
                    507:                return atype;           /* chars, shorts, ints, longs, floats */
                    508:        else if (type == T_DOUBLE)
                    509:                return 4;               /* dword alignment, not qword */
                    510:        else if (type == T_STRUCT || type == T_UNION)
                    511:                return saligntype(sp->s_ip);
                    512:        else if (type == T_ENUM)
                    513:                return mytypes[sp->s_ip->i_type];       /* enum base type */
                    514:        else if (type == T_FSTRUCT || type == T_FUNION || type == T_FENUM) {
                    515:                cerror("alignment of %s \"%s\" is not known",
                    516:                        (type == T_FSTRUCT) ? "struct"
                    517:                      : (type == T_FUNION)  ? "union"
                    518:                      : "enum",
                    519:                        sp->s_id);
                    520:                return 4;
                    521:        }
                    522:        /* T_NONE, T_PTR, T_VOID */
                    523:        cbotch("aligntype type=%d", type);
                    524: }
                    525: 
                    526: /*
                    527:  * Run down a struct INFO list to find alignment type.
                    528:  */
                    529: int
                    530: saligntype(ip) register INFO *ip;
                    531: {
                    532:        register int i, j, max, n;
                    533: 
                    534:        if (alignment != 0)
                    535:                return alignment;
                    536:        n = ip->i_nsp;                  /* number of members */
                    537:        for (i = max = 0; i < n; i++) {
                    538:                j = aligntype(ip->i_sp[i]);
                    539:                if (j > max)
                    540:                        max = j;
                    541:        }
                    542:        return max;
                    543: }
                    544: 
                    545: /*
                    546:  * Given a field type, return an appropriate alignment type.
                    547:  */
                    548: int
                    549: faligntype(t) register int t;
                    550: {
                    551:        if (t <= T_ULONG && t != T_PTR)
                    552:                return mysizes[t];
                    553:        cbotch("faligntype %d", t);
                    554: }
                    555: 
                    556: /*
                    557:  * Check object sizes for overflow.
                    558:  */
                    559: sizeof_t
                    560: szcheck(n, a, s) sizeof_t n; int a; char *s;
                    561: {
                    562:        return n;
                    563: }
                    564: 
                    565: #if    FOLD_DOUBLES
                    566: /*
                    567:  * Convert DCON to/from host double.
                    568:  * Used by the double constant folder in n0/fold.c.
                    569:  * Assumes host fp representation == target fp representation!
                    570:  * The byte orders of the double and DCON are reversed.
                    571:  */
                    572: double
                    573: dval_to_d(tp) TREE *tp;
                    574: {
                    575:        double d;
                    576:        register char *src, *dst;
                    577: 
                    578:        for (src = tp->t_dval, dst = ((char *)&d) + sizeof(d) - 1; dst >= &d; )
                    579:                *dst-- = *src++;
                    580:        return d;
                    581: }
                    582: 
                    583: void
                    584: d_to_dval(tp, d) TREE *tp; double d;
                    585: {
                    586:        register char *src, *dst;
                    587: 
                    588:        for (dst = tp->t_dval, src = ((char *)&d) + sizeof(d) - 1; src >= &d; )
                    589:                *dst++ = *src--;
                    590: }
                    591: #endif
                    592: 
                    593: /* end of n0/i386/bind.c */

unix.superglobalmegacorp.com

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