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

1.1       root        1: /*
                      2:  * This file contains the machine-specific parts of the parser.
                      3:  * It is used in both the SMALL and the LARGE models of segmentation.
                      4:  */
                      5: #ifdef   vax
                      6: #include "INC$LIB:cc0.h"
                      7: #else
                      8: #include "cc0.h"
                      9: #endif
                     10: 
                     11: typedef        struct  locals  {
                     12:        struct  locals *l_lstp;
                     13:        int     l_lofs;
                     14:        int     l_mask;
                     15: }      LOCALS;
                     16: 
                     17: LOCALS *clstp;                 /* Local stack */
                     18: int    clofs;                  /* Current local offset */
                     19: int    cmask;                  /* Current mask */
                     20: int    llofs;                  /* Last local offset reported */
                     21: int    lmask;                  /* Last register mask reported */
                     22: int    lastword = T_PTR;       /* Last 16 bit type */
                     23: char   inbtr[]  = "identifier \"%s\" not bound to register";
                     24: 
                     25: /*
                     26:  * This table is indexed by C type to obtain the size
                     27:  * in bytes of a machine object.
                     28:  * The T_PTR entry is 2; this is for ONLYSMALL.
                     29:  * The entry is patched based on the model.
                     30:  */
                     31: int     mysizes[] = {
                     32:        0,
                     33:        1,      1,
                     34:        2,      2,
                     35:        2,      2,
                     36:        2,
                     37:        4,      4,
                     38:        4,      8,
                     39:        0,
                     40:        0,      0,
                     41:        0,      0,
                     42:        0,      0
                     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,
                     51:        S8,     U8,
                     52:        S16,    U16,
                     53:        S16,    U16,
                     54:        SPTR,
                     55:        S32,    U32,
                     56:        F32,    F64,
                     57:        S16,
                     58:        BLK,    0,
                     59:        BLK,    0,
                     60:        0,      0
                     61: };
                     62: 
                     63: /*
                     64:  * main() calls this routine to perform machine-dependent setup.
                     65:  * On the i8086, it changes the size of a pointer and some other things
                     66:  * that alter the allocation of register variables.
                     67:  */
                     68: vinit()
                     69: {
                     70: #if !ONLYSMALL
                     71:        lastword = T_PTR;
                     72:        mysizes[T_PTR] = 2;
                     73:        mytypes[T_PTR] = SPTR;
                     74:        if (notvariant(VSMALL)) {
                     75:                lastword = T_UINT;
                     76:                mysizes[T_PTR] = 4;
                     77:                mytypes[T_PTR] = LPTR;
                     78:        }
                     79: #endif
                     80: }
                     81: 
                     82: /*
                     83:  * Empty the local binding stack and mark the registers usable
                     84:  * for register variables (SI and DI) as available.
                     85:  */
                     86: initlocals()
                     87: {
                     88:        clstp = NULL;
                     89:        clofs = 0;
                     90:        cmask = BCS|BSS|BSP|BBP;
                     91:        llofs = 0;
                     92:        lmask = BCS|BSS|BSP|BBP;
                     93:        bput(AUTOS);
                     94:        iput((ival_t)clofs);
                     95:        iput((ival_t)cmask);
                     96: }
                     97: 
                     98: /*
                     99:  * Save the current state of the local bindings.
                    100:  */
                    101: savelocals()
                    102: {
                    103:        register LOCALS *lstp;
                    104: 
                    105:        lstp = (LOCALS *) new(sizeof(LOCALS));
                    106:        lstp->l_lstp = clstp;
                    107:        lstp->l_lofs = clofs;
                    108:        lstp->l_mask = cmask;
                    109:        clstp = lstp;
                    110: }
                    111: 
                    112: /*
                    113:  * Restore locals.  Tell the code generator if it changes.
                    114:  */
                    115: restlocals()
                    116: {
                    117:        register LOCALS *lstp;
                    118: 
                    119:        if ((lstp=clstp) == NULL)
                    120:                cbotch("restlocals");
                    121:        clstp = lstp->l_lstp;
                    122:        clofs = lstp->l_lofs;
                    123:        cmask = lstp->l_mask;
                    124:        putautos();
                    125:        free((char *) lstp);
                    126: }
                    127: 
                    128: /*
                    129:  * Bind locals to the correct place on the stack frame.
                    130:  * Where things end up is a function of the model of compilation.
                    131:  */
                    132: bindlocal(sp)
                    133: register SYM   *sp;
                    134: {
                    135:        register int    c, regno;
                    136: 
                    137:        if ((c=sp->s_class) == C_REG) {
                    138:                if ((regno=grabreg(sp)) >= 0) {
                    139:                        sp->s_value = regno;
                    140:                        return;
                    141:                }
                    142:                sp->s_class = C_AUTO;
                    143:                if (isvariant(VSNREG))
                    144:                        cstrict(inbtr, sp->s_id);
                    145:        }
                    146:        if (c==C_AUTO || c==C_REG) {
                    147:                clofs -= ssize(sp);
                    148: #if    OMF286
                    149:                /*
                    150:                 * The 80287 does not function properly for arguments
                    151:                 * on odd boundaries.
                    152:                 * The OMF286 compiler therefore rounds up the offsets
                    153:                 * of autos to keep them on even boundaries;
                    154:                 * however, char and unsigned char autos are not word-aligned.
                    155:                 * The compiler driver must also setvariant(VALIGN) to keep
                    156:                 * the stack word-aligned.
                    157:                 * fieldalign() should also keep structure members
                    158:                 * on word boundaries within the struct, but it does not;
                    159:                 * this is a kludge to maintain compatability with PL/M-286,
                    160:                 * which does not word-align structure members.
                    161:                 * The UDI interface routines fail if structure members
                    162:                 * are forced to word boundaries.
                    163:                 */
                    164:                if (ssize(sp) != 1 && (clofs & 1) != 0)
                    165:                        --clofs;
                    166: #endif
                    167:                sp->s_value = clofs;
                    168:                if (clofs >= 0)
                    169:                        cerror("auto \"%s\" is not addressable", sp->s_id);
                    170:        }
                    171: }
                    172: 
                    173: /*
                    174:  * Attempt to get a register for symbol 'sp'.
                    175:  * Only word things go in registers;
                    176:  * this includes pointers in SMALL model.
                    177:  */
                    178: grabreg(sp)
                    179: register SYM   *sp;
                    180: {
                    181:        register DIM    *dp;
                    182:        register int    type;
                    183: 
                    184:        if ((dp=sp->s_dp) != NULL) {
                    185: #if !ONLYSMALL
                    186:                if (isvariant(VSMALL)) {
                    187: #endif
                    188:                        if (dp->d_type == D_PTR) {
                    189:                                if ((cmask&BSI) == 0) {
                    190:                                        cmask |= BSI;
                    191:                                        return (SI);
                    192:                                }
                    193:                                if ((cmask&BDI) == 0) {
                    194:                                        cmask |= BDI;
                    195:                                        return (DI);
                    196:                                }
                    197:                        }
                    198: #if !ONLYSMALL
                    199:                }
                    200: #endif
                    201:                return (-1);
                    202:        }
                    203:        type = sp->s_type;
                    204:        if (type>=T_SHORT && type<=lastword) {
                    205:                if ((cmask&BSI) == 0) {
                    206:                        cmask |= BSI;
                    207:                        return (SI);
                    208:                }
                    209:                if ((cmask&BDI) == 0) {
                    210:                        cmask |= BDI;
                    211:                        return (DI);
                    212:                }
                    213:        }
                    214:        return (-1);
                    215: }
                    216: 
                    217: /*
                    218:  * Bind arguments.
                    219:  */
                    220: bindargs()
                    221: {
                    222:        register SYM    *sp;
                    223:        register int    i;
                    224:        register sizeof_t offset;
                    225: 
                    226: #if !ONLYSMALL
                    227:        if (isvariant(VSMALL))
                    228:                offset = 8;
                    229:        else
                    230:                offset = 10;
                    231: #else
                    232:        offset = 8;
                    233: #endif
                    234:        for (i=0; i<nargs; ++i) {
                    235:                sp = args[i];
                    236:                if (sp->s_class != C_PREG)
                    237:                        sp->s_class = C_PAUTO;
                    238:                sp->s_value = offset;
                    239:                offset += ssize(sp);
                    240:                if (isvariant(VALIGN) && (offset & 1) != 0)
                    241:                        ++offset;
                    242:                if ((short)offset != offset)
                    243:                    cerror("parameter \"%s\" is not addressible", sp->s_id);
                    244:        }
                    245: }
                    246: 
                    247: /*
                    248:  * Copy register arguments from the stack into the register.
                    249:  * Change class of the argument to plain register.
                    250:  * Note that bindargs() has put the stack displacement
                    251:  * into the 's_value' field of the argument symbol.
                    252:  */
                    253: loadargs()
                    254: {
                    255:        register SYM    *sp;
                    256:        register int    i, r, v;
                    257: 
                    258:        for (i=0; i<nargs; ++i) {
                    259:                sp = args[i];
                    260:                if (sp->s_class == C_PREG) {
                    261:                        if ((r=grabreg(sp)) >= 0) {
                    262:                                v = sp->s_value;
                    263:                                sp->s_class = C_REG;
                    264:                                sp->s_value = r;
                    265:                                loadreg(sp, v);
                    266:                                continue;
                    267:                        }
                    268:                        sp->s_class = C_PAUTO;
                    269:                        if (isvariant(VSNREG))
                    270:                                cstrict(inbtr, sp->s_id);
                    271:                }
                    272:        }
                    273: }
                    274: 
                    275: /*
                    276:  * Load symbol 'sp' from offset 'offset' in the frame.
                    277:  * Since register variables are always words,
                    278:  * the type can always be setup to T_INT.
                    279:  */
                    280: loadreg(sp, offset)
                    281: SYM    *sp;
                    282: {
                    283:        register TREE   *lp, *rp, *tp;
                    284: 
                    285:        newtree(sizeof(TREE));
                    286:        lp = talloc();
                    287:        lp->t_op = REG;
                    288:        lp->t_type = T_INT;
                    289:        lp->t_reg = sp->s_value;
                    290:        rp = talloc();
                    291:        rp->t_op = PID;
                    292:        rp->t_type = T_INT;
                    293:        rp->t_offs = offset;
                    294:        tp = build(ASSIGN, lp, rp);
                    295:        putautos();
                    296:        tput(EEXPR, 0, tp);
                    297: }
                    298: 
                    299: /*
                    300:  * Inform the code generator (and perhaps the optimizer)
                    301:  * about the current automatic variable allocation.
                    302:  * Keep the stack word-aligned if isvariant(VALIGN).
                    303:  */
                    304: putautos()
                    305: {
                    306:        if (clofs != llofs || cmask != lmask) {
                    307:                if (isvariant(VALIGN) && (clofs & 1) != 0)
                    308:                        --clofs;
                    309:                llofs = clofs;
                    310:                lmask = cmask;
                    311:                bput(AUTOS);
                    312:                iput((ival_t)-clofs);
                    313:                iput((ival_t)cmask);
                    314:        }
                    315: }
                    316: 
                    317: /*
                    318:  * Look at type 't', DIM list 'dp' and field width 'w' (0 for non fields)
                    319:  * and return the bit offset of the base of the structure member.
                    320:  * The 'offset' argument is the current bit offset in the structure or union.
                    321:  * Check for fields that are too wide, bad field base types, and arrange
                    322:  * that the byte or word that spans the field can be grabbed in one grab.
                    323:  * See comments in bindlocal() above concerning reals and bitfield alignment.
                    324:  */
                    325: long
                    326: fieldalign(t, dp, ip, w, offset)
                    327: register DIM   *dp;
                    328: INFO           *ip;
                    329: register int   w;
                    330: long           offset;
                    331: {
                    332:        register int    maxwidth;
                    333: 
                    334:        if (w != 0) {                                   /* nonzero width */
                    335:                if (dp != 0)
                    336:                        cerror("non scalar field");
                    337:                if ((maxwidth=8*mysizes[t]) > 16)       /* 8 for char, 16 for int */
                    338:                        cerror("bad base type for field");
                    339:                if (w > maxwidth)
                    340:                        cerror("field too wide");
                    341:                if ((offset&7)+w > maxwidth)
                    342:                        offset = (offset+7) & ~7L;
                    343:        } else {                                        /* zero width */
                    344:                offset = (offset+7) & ~7L;
                    345:        }
                    346:        return (offset);
                    347: }
                    348: 
                    349: /*
                    350:  * Convert a tree into its low level form.
                    351:  * Fill in the machine type byte looking at the C type
                    352:  * and the segment information.
                    353:  */
                    354: TREE *
                    355: transform(tp, why, above)
                    356: register TREE  *tp;
                    357: {
                    358:        register TREE   *lp;
                    359:        register int    t;
                    360:        register int    wd;
                    361: 
                    362:        /*
                    363:         * The way that this code looks at the DIM lists to decide
                    364:         * what type of conversion is inserted makes me sick.
                    365:         * The correct type of conversion node (MUL, DIV, etc.)
                    366:         * should really be inserted when the tree is constructed,
                    367:         * guided by a table.
                    368:         */
                    369:        if (tp->t_op == CONVERT) {
                    370:                lp = tp->t_lp;
                    371:                if (tp->t_dp!=NULL && lp->t_dp==NULL
                    372:                &&  why!=REXPR) {
                    373:                        tp->t_op = MUL;
                    374:                        tp->t_dp = NULL;
                    375:                        if (lp->t_type != T_INT)
                    376:                                tp->t_lp = bconvert(lp, T_INT, NULL,NULL,NULL);
                    377:                        tp->t_type = T_INT;
                    378:                } else if (tp->t_dp==NULL && lp->t_dp!=NULL && tp->t_rp!=NULL) {
                    379:                        tp->t_op = DIV;
                    380:                        lp->t_dp = NULL;
                    381:                        lp->t_type = T_INT;
                    382:                }
                    383:        }
                    384:        /* Fixup any remaining ZCON's */
                    385:        if (tp->t_op == ZCON) {
                    386:                tp->t_op = ICON;
                    387:                if (tp->t_zval > 0xFFFFL)
                    388:                        cwarn("sizeof truncated to unsigned");
                    389:                if (tp->t_zval < 0x8000L)
                    390:                        tp->t_type = T_INT;
                    391:                tp->t_ival = tp->t_zval;
                    392:        }
                    393:        if (tp->t_dp != NULL)
                    394:                tp->t_type = mytypes[T_PTR];
                    395:        else if ((t=tp->t_type)==T_FSTRUCT || t==T_FUNION || t==T_FENUM) {
                    396:                unksize(t, tp->t_ip);
                    397:                tp->t_type = S16;
                    398:        } else {
                    399:                if (t == T_ENUM)
                    400:                        t = tp->t_ip->i_type;
                    401:                tp->t_type = mytypes[t];
                    402:        }
                    403:        if (tp->t_op >= MIOBASE) {
                    404:                wd = why;
                    405:                if (why == REXPR)
                    406:                        wd = EEXPR;
                    407:                tp->t_lp = transform(tp->t_lp, wd, tp->t_op);
                    408:                if (tp->t_op!=FIELD && tp->t_rp!=NULL)
                    409:                        tp->t_rp = transform(tp->t_rp, wd, -1);
                    410:                if (tp->t_op==CONVERT && tp->t_rp==NULL) {
                    411:                        lp = tp->t_lp;
                    412:                        if (tp->t_type == lp->t_type)
                    413:                                tp = lp;
                    414:                }
                    415:        }
                    416:        return (tp);
                    417: }
                    418: 
                    419: /*
                    420:  * Check if the operator 'op', when applied to C types 'lt' and 'rt'
                    421:  * (which are outputs from tltype(), which means that all pointers
                    422:  * have been converted to type T_PTR), involves no conversions.
                    423:  * What this means is that the code generator
                    424:  * has to be prepared to deal with the type mismatch.
                    425:  * This code has been edited too many times; I am really
                    426:  * quite ashamed of the number of bugs that have been
                    427:  * tracked down to this code. It is no longer amusing.
                    428:  */
                    429: noconvert(op, lt, rt)
                    430: register int   op;
                    431: register int   lt;
                    432: register int   rt;
                    433: {
                    434:        if (op==ASSIGN || op==CAST || (op>=EQ && op<=ULT)) {
                    435:                if ((lt>=T_CHAR && lt<=T_UCHAR)
                    436:                &&  (rt>=T_CHAR && rt<=T_UCHAR))
                    437:                        return(1);
                    438:                if ((lt>=T_SHORT && lt<=T_UINT) 
                    439:                &&  (rt>=T_SHORT && rt<=T_UINT))
                    440:                        return (1);
                    441:                if ((lt>=T_LONG  && lt<=T_ULONG)
                    442:                &&  (rt>=T_LONG  && rt<=T_ULONG))
                    443:                        return (1);
                    444:                if (lt==T_PTR && rt==T_PTR)
                    445:                        return (1);
                    446: #if !ONLYSMALL
                    447:                if (notvariant(VSMALL)
                    448:                &&   op != CAST) {
                    449:                        if ((lt>=T_SHORT && lt<=T_ULONG)
                    450:                        &&  (rt>=T_SHORT && rt<=T_ULONG)
                    451:                        &&  (lt==T_PTR || rt==T_PTR))
                    452:                                return (1);
                    453:                } else if (isvariant(VSMALL)) {
                    454: #endif
                    455:                        if ((lt>=T_SHORT && lt<=T_PTR)
                    456:                        &&  (rt>=T_SHORT && rt<=T_PTR))
                    457:                                return (1);
                    458: #if !ONLYSMALL
                    459:                }
                    460: #endif
                    461:                if (op==CAST && lt==T_FLOAT && rt==T_DOUBLE)
                    462:                        return (1);
                    463:        }
                    464:        return (0);
                    465: }
                    466: 
                    467: /*
                    468:  * Put out an ALIGN object of the correct flavor to align
                    469:  * the location counter well enough for the object to which 'sp' points.
                    470:  * On the i8086 there is only one type of alignment,
                    471:  * so the argument is unused.
                    472:  */
                    473: align(sp)
                    474: SYM    *sp;
                    475: {
                    476:        bput(ALIGN);
                    477:        bput(0);
                    478: }
                    479: 
                    480: /*
                    481:  * Check object sizes for overflow.
                    482:  */
                    483: sizeof_t szcheck(n, a, s) sizeof_t n; int a; char *s;
                    484: {
                    485:        if (n < 0x10000L)
                    486:                return n;
                    487:        if (a == 0 || (n & ~MAXUV) != 0) {
                    488:                cerror("size of %s too large", s);
                    489:                return(0);
                    490:        }
                    491:        if (isvariant(VSLCON))
                    492:                cstrict("size of %s overflows fsize_t", s);
                    493:        return (n);
                    494: }

unix.superglobalmegacorp.com

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