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