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