1: # include "pass1.h" 2: # include <sys/types.h> 3: # include <a.out.h> 4: # include <stab.h> 5: 6: int proflg = 0; /* are we generating profiling code? */ 7: int strftn = 0; /* is the current function one which returns a value */ 8: int gdebug; 9: int fdefflag; /* are we within a function definition ? */ 10: char NULLNAME[8]; 11: int labelno; 12: 13: # define putstr(s) fputs((s), stdout) 14: 15: branch( n ){ 16: /* output a branch to label n */ 17: /* exception is an ordinary function branching to retlab: then, return */ 18: if( n == retlab && !strftn ){ 19: putstr( " jmp cret\n" ); 20: } 21: else printf( " jbr L%d\n", n ); 22: } 23: 24: int lastloc = { -1 }; 25: 26: defalign(n) { 27: /* cause the alignment to become a multiple of n */ 28: n /= SZCHAR; 29: if( lastloc != PROG && n > 1 ) printf( " .even\n" ); 30: } 31: 32: locctr( l ){ 33: register temp; 34: /* l is PROG, ADATA, DATA, STRNG, ISTRNG, or STAB */ 35: 36: if( l == lastloc ) return(l); 37: temp = lastloc; 38: lastloc = l; 39: switch( l ){ 40: 41: case PROG: 42: putstr( " .text\n" ); 43: psline(); 44: break; 45: 46: case DATA: 47: case ADATA: 48: putstr( " .data\n" ); 49: break; 50: 51: case STRNG: 52: case ISTRNG: 53: break; 54: 55: case STAB: 56: cerror( "locctr: STAB unused" ); 57: break; 58: 59: default: 60: cerror( "illegal location counter" ); 61: } 62: 63: return( temp ); 64: } 65: 66: deflab( n ){ 67: /* output something to define the current position as label n */ 68: printf( "L%d:\n", n ); 69: } 70: 71: int crslab = 10; 72: 73: getlab(){ 74: /* return a number usable for a label */ 75: return( ++crslab ); 76: } 77: 78: efcode(){ 79: /* code for the end of a function */ 80: 81: if( strftn ){ /* copy output (in R0) to caller */ 82: register NODE *l, *r; 83: register struct symtab *p; 84: register TWORD t; 85: int i; 86: 87: p = &stab[curftn]; 88: t = p->stype; 89: t = DECREF(t); 90: 91: deflab( retlab ); 92: 93: i = getlab(); /* label for return area */ 94: #ifndef LCOMM 95: putstr(" .bss\n" ); 96: printf("L%d: .=.+%d.\n", i, tsize(t, p->dimoff, p->sizoff)/SZCHAR ); 97: putstr(" .text\n" ); 98: #else 99: { int sz = tsize(t, p->dimoff, p->sizoff) / SZCHAR; 100: if (sz % sizeof (int)) 101: sz += sizeof (int) - (sz % sizeof (int)); 102: printf(" .lcomm L%d,%d\n", i, sz); 103: } 104: #endif 105: psline(); 106: printf(" mov $L%d,r1\n", i); 107: 108: reached = 1; 109: l = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff ); 110: l->tn.rval = 1; /* R1 */ 111: l->tn.lval = 0; /* no offset */ 112: r = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff ); 113: r->tn.rval = 0; /* R0 */ 114: r->tn.lval = 0; 115: l = buildtree( UNARY MUL, l, NIL ); 116: r = buildtree( UNARY MUL, r, NIL ); 117: l = buildtree( ASSIGN, l, r ); 118: l->in.op = FREE; 119: ecomp( l->in.left ); 120: printf( " mov $L%d,r0\n", i ); 121: /* turn off strftn flag, so return sequence will be generated */ 122: strftn = 0; 123: } 124: branch( retlab ); 125: p2bend(); 126: fdefflag = 0; 127: } 128: 129: bfcode( a, n ) int a[]; { 130: /* code for the beginning of a function; a is an array of 131: indices in stab for the arguments; n is the number */ 132: register i; 133: register temp; 134: register struct symtab *p; 135: OFFSZ off; 136: 137: locctr( PROG ); 138: p = &stab[curftn]; 139: defnam( p ); 140: temp = p->stype; 141: temp = DECREF(temp); 142: strftn = (temp==STRTY) || (temp==UNIONTY); 143: 144: retlab = getlab(); 145: 146: /* routine prolog */ 147: 148: if( proflg ){ /* profile code */ 149: i = getlab(); 150: printf( " mov $L%d,r0\n", i ); 151: printf( " jsr pc,mcount\n" ); 152: printf( " .bss\nL%d: .=.+2\n .text\n", i ); 153: } 154: 155: printf( " jsr r5,csv\n" ); 156: /* adjust stack for autos */ 157: printf( " sub $.F%d,sp\n", ftnno ); 158: 159: off = ARGINIT; 160: 161: for( i=0; i<n; ++i ){ 162: p = &stab[a[i]]; 163: if( p->sclass == REGISTER ){ 164: temp = p->offset; /* save register number */ 165: p->sclass = PARAM; /* forget that it is a register */ 166: p->offset = NOOFFSET; 167: oalloc( p, &off ); 168: printf( " mov %d.(r5),r%d\n", p->offset/SZCHAR, temp); 169: p->offset = temp; /* remember register number */ 170: p->sclass = REGISTER; /* remember that it is a register */ 171: } 172: else if( p->stype == STRTY || p->stype == UNIONTY ) { 173: p->offset = NOOFFSET; 174: if( oalloc( p, &off ) ) cerror( "bad argument" ); 175: SETOFF( off, ALSTACK ); 176: } 177: else { 178: if( oalloc( p, &off ) ) cerror( "bad argument" ); 179: } 180: 181: } 182: if (gdebug) { 183: #ifdef STABDOT 184: pstabdot(N_SLINE, lineno); 185: #else 186: pstab(NULLNAME, N_SLINE); 187: printf("0,%d,LL%d\n", lineno, labelno); 188: printf("LL%d:\n", labelno++); 189: #endif 190: } 191: fdefflag = 1; 192: } 193: 194: bccode(){ /* called just before the first executable statment */ 195: /* by now, the automatics and register variables are allocated */ 196: SETOFF( autooff, SZINT ); 197: /* set aside store area offset */ 198: p2bbeg( autooff, regvar ); 199: } 200: 201: ejobcode( flag ){ 202: /* called just before final exit */ 203: /* flag is 1 if errors, 0 if none */ 204: } 205: 206: aobeg(){ 207: /* called before removing automatics from stab */ 208: } 209: 210: aocode(p) struct symtab *p; { 211: /* called when automatic p removed from stab */ 212: } 213: 214: aoend(){ 215: /* called after removing all automatics from stab */ 216: } 217: 218: defnam( p ) register struct symtab *p; { 219: /* define the current location as the name p->sname */ 220: 221: if( p->sclass == EXTDEF ){ 222: printf( " .globl %s\n", exname( p->sname ) ); 223: } 224: if( p->sclass == STATIC && p->slevel>1 ) deflab( (int)p->offset ); 225: else printf( "%s:\n", exname( p->sname ) ); 226: 227: } 228: 229: bycode( t, i ){ 230: #ifdef ASSTRINGS 231: static int lastoctal = 0; 232: #endif 233: 234: /* put byte i+1 in a string */ 235: 236: #ifdef ASSTRINGS 237: 238: i &= 077; 239: if ( t < 0 ){ 240: if ( i != 0 ) putstr( "\"\n" ); 241: } else { 242: if ( i == 0 ) putstr("\t.ascii\t\""); 243: if ( t == '\\' || t == '"'){ 244: lastoctal = 0; 245: printf("\\%c", t); 246: } 247: /* 248: * We escape the colon in strings so that 249: * c2 will, in its infinite wisdom, interpret 250: * the characters preceding the colon as a label. 251: * If we didn't escape the colon, c2 would 252: * throw away any trailing blanks or tabs after 253: * the colon, but reconstruct a assembly 254: * language semantically correct program. 255: * C2 hasn't been taught about strings. 256: */ 257: else if ( t == ':' || t < 040 || t >= 0177 ){ 258: lastoctal++; 259: printf("\\%o",t); 260: } 261: else if ( lastoctal && '0' <= t && t <= '9' ){ 262: lastoctal = 0; 263: printf("\"\n\t.ascii\t\"%c", t ); 264: } 265: else 266: { 267: lastoctal = 0; 268: putchar(t); 269: } 270: if ( i == 077 ) putstr("\"\n"); 271: } 272: #else 273: 274: i &= 07; 275: if( t < 0 ){ /* end of the string */ 276: if( i != 0 ) putchar( '\n' ); 277: } 278: 279: else { /* stash byte t into string */ 280: if( i == 0 ) putstr( " .byte " ); 281: else putchar( ',' ); 282: printf( "0x%x", t ); 283: if( i == 07 ) putchar( '\n' ); 284: } 285: #endif 286: } 287: 288: zecode( n ){ 289: /* n integer words of zeros */ 290: OFFSZ temp; 291: register i; 292: 293: if( n <= 0 ) return; 294: printf( " " ); 295: for( i=1; i<n; i++ ) { 296: if( i%8 == 0 ) 297: printf( "\n " ); 298: printf( "0; " ); 299: } 300: printf( "0\n" ); 301: temp = n; 302: inoff += temp*SZINT; 303: } 304: 305: fldal( t ) unsigned t; { /* return the alignment of field of type t */ 306: uerror( "illegal field type" ); 307: return( ALINT ); 308: } 309: 310: fldty( p ) struct symtab *p; { /* fix up type of field p */ 311: ; 312: } 313: 314: where(c){ /* print location of error */ 315: /* c is either 'u', 'c', or 'w' */ 316: /* GCOS version */ 317: fprintf( stderr, "%s, line %d: ", ftitle, lineno ); 318: } 319: 320: main( argc, argv ) char *argv[]; { 321: #ifdef BUFSTDERR 322: char errbuf[BUFSIZ]; 323: setbuf(stderr, errbuf); 324: #endif 325: return(mainp1( argc, argv )); 326: } 327: 328: struct sw heapsw[SWITSZ]; /* heap for switches */ 329: 330: genswitch(p,n) register struct sw *p;{ 331: /* p points to an array of structures, each consisting 332: of a constant value and a label. 333: The first is >=0 if there is a default label; 334: its value is the label number 335: The entries p[1] to p[n] are the nontrivial cases 336: */ 337: register i; 338: register CONSZ j, range; 339: register dlab, swlab; 340: 341: range = p[n].sval-p[1].sval; 342: 343: if( range>0 && range <= 3*n && n>=4 ){ /* implement a direct switch */ 344: 345: swlab = getlab(); 346: dlab = p->slab >= 0 ? p->slab : getlab(); 347: 348: if( p[1].sval ){ 349: printf( " sub $" ); 350: printf( CONFMT, p[1].sval ); 351: printf( ".,r0\n" ); 352: } 353: 354: /* note that this is a cl; it thus checks 355: for numbers below range as well as out of range. 356: */ 357: printf( " cmp r0,$%ld.\n", range ); 358: printf( " jhi L%d\n", dlab ); 359: 360: printf( " asl r0\n" ); 361: printf( " jmp *L%d(r0)\n", swlab ); 362: 363: /* output table */ 364: 365: locctr( ADATA ); 366: defalign( ALPOINT ); 367: deflab( swlab ); 368: 369: for( i=1,j=p[1].sval; i<=n; ++j ){ 370: 371: printf( " L%d\n", ( j == p[i].sval ) ? 372: p[i++].slab : dlab ); 373: } 374: 375: locctr( PROG ); 376: 377: if( p->slab< 0 ) deflab( dlab ); 378: return; 379: 380: } 381: 382: if( n>8 ) { /* heap switch */ 383: 384: heapsw[0].slab = dlab = p->slab >= 0 ? p->slab : getlab(); 385: makeheap(p, n, 1); /* build heap */ 386: 387: walkheap(1, n); /* produce code */ 388: 389: if( p->slab >= 0 ) 390: branch( dlab ); 391: else 392: printf("L%d:\n", dlab); 393: return; 394: } 395: 396: /* debugging code */ 397: 398: /* out for the moment 399: if( n >= 4 ) werror( "inefficient switch: %d, %d", n, (int) (range/n) ); 400: */ 401: 402: /* simple switch code */ 403: 404: for( i=1; i<=n; ++i ){ 405: /* already in r0 */ 406: 407: putstr( " cmp r0,$" ); 408: printf( CONFMT, p[i].sval ); 409: printf( ".\n jeq L%d\n", p[i].slab ); 410: } 411: 412: if( p->slab>=0 ) branch( p->slab ); 413: } 414: 415: makeheap(p, m, n) 416: register struct sw *p; 417: { 418: register int q; 419: 420: q = select(m); 421: heapsw[n] = p[q]; 422: if( q>1 ) makeheap(p, q-1, 2*n); 423: if( q<m ) makeheap(p+q, m-q, 2*n+1); 424: } 425: 426: select(m) { 427: register int l,i,k; 428: 429: for(i=1; ; i*=2) 430: if( (i-1) > m ) break; 431: l = ((k = i/2 - 1) + 1)/2; 432: return( l + (m-k < l ? m-k : l)); 433: } 434: 435: walkheap(start, limit) 436: { 437: int label; 438: 439: 440: if( start > limit ) return; 441: printf(" cmp r0,$%d.\n", heapsw[start].sval); 442: printf(" jeq L%d\n", heapsw[start].slab); 443: if( (2*start) > limit ) { 444: printf(" jbr L%d\n", heapsw[0].slab); 445: return; 446: } 447: if( (2*start+1) <= limit ) { 448: label = getlab(); 449: printf(" jgt L%d\n", label); 450: } else 451: printf(" jgt L%d\n", heapsw[0].slab); 452: walkheap( 2*start, limit); 453: if( (2*start+1) <= limit ) { 454: printf("L%d:\n", label); 455: walkheap( 2*start+1, limit); 456: } 457: }