|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.