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