|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)code.c 1.6 (Berkeley) 5/31/88"; ! 3: #endif ! 4: ! 5: # include "pass1.h" ! 6: # include <sys/types.h> ! 7: # include <a.out.h> ! 8: # include <stab.h> ! 9: ! 10: int proflg = 0; /* are we generating profiling code? */ ! 11: int strftn = 0; /* is the current function one which returns a value */ ! 12: int gdebug; ! 13: int fdefflag; /* are we within a function definition ? */ ! 14: #ifndef STABDOT ! 15: char NULLNAME[8]; ! 16: #endif ! 17: int labelno; ! 18: ! 19: # define putstr(s) fputs((s), stdout) ! 20: ! 21: branch( n ){ ! 22: /* output a branch to label n */ ! 23: /* exception is an ordinary function branching to retlab: then, return */ ! 24: if( nerrors ) return; ! 25: if( n == retlab && !strftn ){ ! 26: register TWORD t; ! 27: register r; ! 28: /* set number of regs in assem comment field */ ! 29: /* so optimizers can do a better job */ ! 30: r = 0; ! 31: if( retstat & RETVAL ){ /* the function rets a val somewhere */ ! 32: t = (&stab[curftn])->stype; ! 33: t = DECREF(t); ! 34: r++; /* it is at least one */ ! 35: if(t == DOUBLE) ! 36: r++; /* it takes two */ ! 37: } else /* the fn does not ret a val */ ! 38: r = 2; ! 39: printf( " ret#%d\n", r ); ! 40: } ! 41: else printf( " jbr L%d\n", n ); ! 42: } ! 43: ! 44: int lastloc = { -1 }; ! 45: ! 46: short log2tab[] = {0, 0, 1, 2, 2, 3, 3, 3, 3}; ! 47: #define LOG2SZ 9 ! 48: ! 49: defalign(n) { ! 50: /* cause the alignment to become a multiple of n */ ! 51: n /= SZCHAR; ! 52: if( lastloc != PROG && n > 1 ) printf( " .align %d\n", n >= 0 && n < LOG2SZ ? log2tab[n] : 0 ); ! 53: } ! 54: ! 55: locctr( l ){ ! 56: register temp; ! 57: /* l is PROG, ADATA, DATA, STRNG, ISTRNG, or STAB */ ! 58: ! 59: if( l == lastloc ) return(l); ! 60: temp = lastloc; ! 61: lastloc = l; ! 62: if( nerrors ) return(temp); ! 63: switch( l ){ ! 64: ! 65: case PROG: ! 66: putstr( " .text\n" ); ! 67: psline(); ! 68: break; ! 69: ! 70: case DATA: ! 71: case ADATA: ! 72: putstr( " .data\n" ); ! 73: break; ! 74: ! 75: case STRNG: ! 76: putstr( " .data 1\n" ); ! 77: break; ! 78: ! 79: case ISTRNG: ! 80: putstr( " .data 2\n" ); ! 81: break; ! 82: ! 83: case STAB: ! 84: putstr( " .stab\n" ); ! 85: break; ! 86: ! 87: default: ! 88: cerror( "illegal location counter" ); ! 89: } ! 90: ! 91: return( temp ); ! 92: } ! 93: ! 94: deflab( n ){ ! 95: /* output something to define the current position as label n */ ! 96: if (nerrors) return; ! 97: printf( "L%d:\n", n ); ! 98: } ! 99: ! 100: int crslab = 10; ! 101: ! 102: getlab(){ ! 103: /* return a number usable for a label */ ! 104: return( ++crslab ); ! 105: } ! 106: ! 107: ! 108: efcode(){ ! 109: /* code for the end of a function */ ! 110: ! 111: if( strftn ){ /* copy output (in R2) to caller */ ! 112: register NODE *l, *r; ! 113: register struct symtab *p; ! 114: register TWORD t; ! 115: register int i; ! 116: ! 117: p = &stab[curftn]; ! 118: t = p->stype; ! 119: t = DECREF(t); ! 120: ! 121: deflab( retlab ); ! 122: ! 123: i = getlab(); /* label for return area */ ! 124: #ifndef LCOMM ! 125: putstr(" .data\n" ); ! 126: putstr(" .align 2\n" ); ! 127: printf("L%d: .space %d\n", i, tsize(t, p->dimoff, p->sizoff)/SZCHAR ); ! 128: putstr(" .text\n" ); ! 129: #else ! 130: { int sz = tsize(t, p->dimoff, p->sizoff) / SZCHAR; ! 131: if (sz % (SZINT/SZCHAR)) ! 132: sz += (SZINT/SZCHAR) - (sz % (SZINT/SZCHAR)); ! 133: printf(" .lcomm L%d,%d\n", i, sz); ! 134: } ! 135: #endif ! 136: psline(); ! 137: printf(" movab L%d,r1\n", i); ! 138: ! 139: reached = 1; ! 140: l = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff ); ! 141: l->tn.rval = 1; /* R1 */ ! 142: l->tn.lval = 0; /* no offset */ ! 143: r = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff ); ! 144: r->tn.rval = 0; /* R0 */ ! 145: r->tn.lval = 0; ! 146: l = buildtree( UNARY MUL, l, NIL ); ! 147: r = buildtree( UNARY MUL, r, NIL ); ! 148: l = buildtree( ASSIGN, l, r ); ! 149: l->in.op = FREE; ! 150: ecomp( l->in.left ); ! 151: printf( " movab L%d,r0\n", i ); ! 152: /* turn off strftn flag, so return sequence will be generated */ ! 153: strftn = 0; ! 154: } ! 155: branch( retlab ); ! 156: p2bend(); ! 157: fdefflag = 0; ! 158: } ! 159: ! 160: int ftlab1, ftlab2; ! 161: ! 162: bfcode( a, n ) int a[]; { ! 163: /* code for the beginning of a function; a is an array of ! 164: indices in stab for the arguments; n is the number */ ! 165: register i; ! 166: register temp; ! 167: register struct symtab *p; ! 168: int off; ! 169: #ifdef REG_CHAR ! 170: char *toreg(); ! 171: #endif ! 172: char *rname(); ! 173: ! 174: if( nerrors ) return; ! 175: (void) locctr( PROG ); ! 176: p = &stab[curftn]; ! 177: putstr( " .align 1\n"); ! 178: defnam( p ); ! 179: temp = p->stype; ! 180: temp = DECREF(temp); ! 181: strftn = (temp==STRTY) || (temp==UNIONTY); ! 182: ! 183: retlab = getlab(); ! 184: ! 185: /* routine prolog */ ! 186: ! 187: printf( " .word L%d\n", ftnno); ! 188: ftlab1 = getlab(); ! 189: ftlab2 = getlab(); ! 190: printf( " jbr L%d\n", ftlab1); ! 191: printf( "L%d:\n", ftlab2); ! 192: if( proflg ) { /* profile code */ ! 193: i = getlab(); ! 194: printf(" pushl $L%d\n", i); ! 195: putstr(" callf $8,mcount\n"); ! 196: putstr(" .data\n"); ! 197: putstr(" .align 2\n"); ! 198: printf("L%d: .long 0\n", i); ! 199: putstr(" .text\n"); ! 200: psline(); ! 201: } ! 202: ! 203: off = ARGINIT; ! 204: ! 205: for( i=0; i<n; ++i ){ ! 206: p = &stab[a[i]]; ! 207: if( p->sclass == REGISTER ){ ! 208: temp = p->offset; /* save register number */ ! 209: p->sclass = PARAM; /* forget that it is a register */ ! 210: p->offset = NOOFFSET; ! 211: (void) oalloc( p, &off ); ! 212: #ifdef REG_CHAR ! 213: printf( " %s", toreg(p->stype)) ); ! 214: #else ! 215: putstr(" movl"); ! 216: #endif ! 217: printf( " %d(fp),%s\n", p->offset/SZCHAR, rname(temp) ); ! 218: p->offset = temp; /* remember register number */ ! 219: p->sclass = REGISTER; /* remember that it is a register */ ! 220: #ifdef REG_CHAR ! 221: temp = p->stype; ! 222: if( temp==CHAR || temp==SHORT ) ! 223: p->stype = INT; ! 224: else if( temp==UCHAR || temp==USHORT ) ! 225: p->stype = UNSIGNED; ! 226: #endif ! 227: } ! 228: else if( p->stype == STRTY || p->stype == UNIONTY ) { ! 229: p->offset = NOOFFSET; ! 230: if( oalloc( p, &off ) ) cerror( "bad argument" ); ! 231: SETOFF( off, ALSTACK ); ! 232: } ! 233: else { ! 234: if( oalloc( p, &off ) ) cerror( "bad argument" ); ! 235: } ! 236: ! 237: } ! 238: if (gdebug && !nerrors) { ! 239: #ifdef STABDOT ! 240: pstabdot(N_SLINE, lineno); ! 241: #else ! 242: pstab(NULLNAME, N_SLINE); ! 243: printf("0,%d,LL%d\n", lineno, labelno); ! 244: printf("LL%d:\n", labelno++); ! 245: #endif ! 246: } ! 247: fdefflag = 1; ! 248: } ! 249: ! 250: bccode(){ /* called just before the first executable statment */ ! 251: /* by now, the automatics and register variables are allocated */ ! 252: SETOFF( autooff, SZINT ); ! 253: /* set aside store area offset */ ! 254: p2bbeg( autooff, regvar ); ! 255: } ! 256: ! 257: /*ARGSUSED*/ ! 258: ejobcode( flag ){ ! 259: /* called just before final exit */ ! 260: /* flag is 1 if errors, 0 if none */ ! 261: } ! 262: ! 263: #ifndef aobeg ! 264: aobeg(){ ! 265: /* called before removing automatics from stab */ ! 266: } ! 267: #endif aobeg ! 268: ! 269: #ifndef aocode ! 270: /*ARGSUSED*/ ! 271: aocode(p) struct symtab *p; { ! 272: /* called when automatic p removed from stab */ ! 273: } ! 274: #endif aocode ! 275: ! 276: #ifndef aoend ! 277: aoend(){ ! 278: /* called after removing all automatics from stab */ ! 279: } ! 280: #endif aoend ! 281: ! 282: defnam( p ) register struct symtab *p; { ! 283: /* define the current location as the name p->sname */ ! 284: ! 285: if( p->sclass == EXTDEF ){ ! 286: printf( " .globl %s\n", exname( p->sname ) ); ! 287: } ! 288: if( p->sclass == STATIC && p->slevel>1 ) deflab( p->offset ); ! 289: else printf( "%s:\n", exname( p->sname ) ); ! 290: ! 291: } ! 292: ! 293: bycode( t, i ){ ! 294: #ifdef ASSTRINGS ! 295: static int lastoctal = 0; ! 296: #endif ! 297: ! 298: /* put byte i+1 in a string */ ! 299: ! 300: if ( nerrors ) return; ! 301: #ifdef ASSTRINGS ! 302: ! 303: i &= 077; ! 304: if ( t < 0 ){ ! 305: if ( i != 0 ) putstr( "\"\n" ); ! 306: } else { ! 307: if ( i == 0 ) putstr("\t.ascii\t\""); ! 308: if ( t == '\\' || t == '"'){ ! 309: lastoctal = 0; ! 310: printf("\\%c", t); ! 311: } ! 312: else if ( t < 040 || t >= 0177 ){ ! 313: lastoctal++; ! 314: printf("\\%o",t); ! 315: } ! 316: else if ( lastoctal && '0' <= t && t <= '9' ){ ! 317: lastoctal = 0; ! 318: printf("\"\n\t.ascii\t\"%c", t ); ! 319: } ! 320: else ! 321: { ! 322: lastoctal = 0; ! 323: putchar(t); ! 324: } ! 325: if ( i == 077 ) putstr("\"\n"); ! 326: } ! 327: #else ! 328: ! 329: i &= 07; ! 330: if( t < 0 ){ /* end of the string */ ! 331: if( i != 0 ) putchar( '\n' ); ! 332: } ! 333: ! 334: else { /* stash byte t into string */ ! 335: if( i == 0 ) putstr( " .byte " ); ! 336: else putchar( ',' ); ! 337: printf( "0x%x", t ); ! 338: if( i == 07 ) putchar( '\n' ); ! 339: } ! 340: #endif ! 341: } ! 342: ! 343: zecode( n ){ ! 344: /* n integer words of zeros */ ! 345: OFFSZ temp; ! 346: if( n <= 0 ) return; ! 347: printf( " .space %d\n", (SZINT/SZCHAR)*n ); ! 348: temp = n; ! 349: inoff += temp*SZINT; ! 350: } ! 351: ! 352: /*ARGSUSED*/ ! 353: fldal( t ) unsigned t; { /* return the alignment of field of type t */ ! 354: uerror( "illegal field type" ); ! 355: return( ALINT ); ! 356: } ! 357: ! 358: /*ARGSUSED*/ ! 359: fldty( p ) struct symtab *p; { /* fix up type of field p */ ! 360: ; ! 361: } ! 362: ! 363: /*ARGSUSED*/ ! 364: where(c){ /* print location of error */ ! 365: /* c is either 'u', 'c', or 'w' */ ! 366: /* GCOS version */ ! 367: fprintf( stderr, "%s, line %d: ", ftitle, lineno ); ! 368: } ! 369: ! 370: ! 371: #ifdef REG_CHAR ! 372: /* tbl - toreg() returns a pointer to a char string ! 373: which is the correct "register move" for the passed type ! 374: */ ! 375: struct type_move {TWORD fromtype; char tostrng[8];} toreg_strs[] = ! 376: { ! 377: CHAR, "cvtbl", ! 378: SHORT, "cvtwl", ! 379: UCHAR, "movzbl", ! 380: USHORT, "movzwl", ! 381: 0, "movl" ! 382: }; ! 383: ! 384: char ! 385: *toreg(type) ! 386: TWORD type; ! 387: { ! 388: struct type_move *p; ! 389: ! 390: for ( p=toreg_strs; p->fromtype != 0; p++) ! 391: if (p->fromtype == type) return(p->tostrng); ! 392: ! 393: /* type not found, must be a word type */ ! 394: return(p->tostrng); ! 395: } ! 396: /* tbl */ ! 397: #endif ! 398: ! 399: ! 400: main( argc, argv ) char *argv[]; { ! 401: #ifdef BUFSTDERR ! 402: char errbuf[BUFSIZ]; ! 403: setbuf(stderr, errbuf); ! 404: #endif ! 405: return(mainp1( argc, argv )); ! 406: } ! 407: ! 408: struct sw heapsw[SWITSZ]; /* heap for switches */ ! 409: ! 410: genswitch(p,n) register struct sw *p;{ ! 411: /* p points to an array of structures, each consisting ! 412: of a constant value and a label. ! 413: The first is >=0 if there is a default label; ! 414: its value is the label number ! 415: The entries p[1] to p[n] are the nontrivial cases ! 416: */ ! 417: register i; ! 418: register CONSZ j; ! 419: register CONSZ unsigned range; ! 420: register dlab, swlab; ! 421: ! 422: if( nerrors ) return; ! 423: range = p[n].sval-p[1].sval; ! 424: ! 425: if( range <= 3*n && n>=4 ){ /* implement a direct switch */ ! 426: ! 427: swlab = getlab(); ! 428: dlab = p->slab >= 0 ? p->slab : getlab(); ! 429: ! 430: /* already in r0 */ ! 431: putstr( " casel r0,$" ); ! 432: printf( CONFMT, p[1].sval ); ! 433: putstr(",$"); ! 434: printf( CONFMT, range); ! 435: printf("\n .align 1\nL%d:\n", swlab); ! 436: for( i=1,j=p[1].sval; i<=n; j++) { ! 437: printf(" .word L%d-L%d\n", (j == p[i].sval ? ((j=p[i++].sval), p[i-1].slab) : dlab), ! 438: swlab); ! 439: } ! 440: ! 441: if( p->slab >= 0 ) branch( dlab ); ! 442: else printf("L%d:\n", dlab); ! 443: return; ! 444: ! 445: } ! 446: ! 447: if( n>8 ) { /* heap switch */ ! 448: ! 449: heapsw[0].slab = dlab = p->slab >= 0 ? p->slab : getlab(); ! 450: makeheap(p, n, 1); /* build heap */ ! 451: ! 452: walkheap(1, n); /* produce code */ ! 453: ! 454: if( p->slab >= 0 ) ! 455: branch( dlab ); ! 456: else ! 457: printf("L%d:\n", dlab); ! 458: return; ! 459: } ! 460: ! 461: /* debugging code */ ! 462: ! 463: /* out for the moment ! 464: if( n >= 4 ) werror( "inefficient switch: %d, %d", n, (int) (range/n) ); ! 465: */ ! 466: ! 467: /* simple switch code */ ! 468: ! 469: for( i=1; i<=n; ++i ){ ! 470: /* already in r0 */ ! 471: ! 472: putstr( " cmpl r0,$" ); ! 473: printf( CONFMT, p[i].sval ); ! 474: printf( "\n jeql L%d\n", p[i].slab ); ! 475: } ! 476: ! 477: if( p->slab>=0 ) branch( p->slab ); ! 478: } ! 479: ! 480: makeheap(p, m, n) ! 481: register struct sw *p; ! 482: { ! 483: register int q; ! 484: ! 485: q = selectheap(m); ! 486: heapsw[n] = p[q]; ! 487: if( q>1 ) makeheap(p, q-1, 2*n); ! 488: if( q<m ) makeheap(p+q, m-q, 2*n+1); ! 489: } ! 490: ! 491: selectheap(m) { ! 492: register int l,i,k; ! 493: ! 494: for(i=1; ; i*=2) ! 495: if( (i-1) > m ) break; ! 496: l = ((k = i/2 - 1) + 1)/2; ! 497: return( l + (m-k < l ? m-k : l)); ! 498: } ! 499: ! 500: walkheap(start, limit) ! 501: { ! 502: int label; ! 503: ! 504: ! 505: if( start > limit ) return; ! 506: putstr( " cmpl r0,$" ); ! 507: printf( CONFMT, heapsw[start].sval); ! 508: printf("\n jeql L%d\n", heapsw[start].slab); ! 509: if( (2*start) > limit ) { ! 510: printf(" jbr L%d\n", heapsw[0].slab); ! 511: return; ! 512: } ! 513: if( (2*start+1) <= limit ) { ! 514: label = getlab(); ! 515: printf(" jgtr L%d\n", label); ! 516: } else ! 517: printf(" jgtr L%d\n", heapsw[0].slab); ! 518: walkheap( 2*start, limit); ! 519: if( (2*start+1) <= limit ) { ! 520: printf("L%d:\n", label); ! 521: walkheap( 2*start+1, limit); ! 522: } ! 523: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.