Research V7 development
[unix-history] / usr / src / cmd / pcc / code.c
CommitLineData
3c5d933b
SJ
1# include <stdio.h>
2# include <signal.h>
3
4# include "mfile1"
5
6int proflag;
7int strftn = 0; /* is the current function one which returns a value */
8FILE *tmpfile;
9FILE *outfile = stdout;
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( " jmp cret\n" );
16 }
17 else printf( " jbr L%d\n", n );
18 }
19
20int lastloc = PROG;
21
22defalign(n) {
23 /* cause the alignment to become a multiple of n */
24 n /= SZCHAR;
25 if( lastloc != PROG && n > 1 ) printf( " .even\n" );
26 }
27
28locctr( l ){
29 register temp;
30 /* l is PROG, ADATA, DATA, STRNG, ISTRNG, or STAB */
31
32 if( l == lastloc ) return(l);
33 temp = lastloc;
34 lastloc = l;
35 switch( l ){
36
37 case PROG:
38 outfile = stdout;
39 printf( " .text\n" );
40 break;
41
42 case DATA:
43 case ADATA:
44 outfile = stdout;
45 if( temp != DATA && temp != ADATA )
46 printf( " .data\n" );
47 break;
48
49 case STRNG:
50 case ISTRNG:
51 outfile = tmpfile;
52 break;
53
54 case STAB:
55 cerror( "locctr: STAB unused" );
56 break;
57
58 default:
59 cerror( "illegal location counter" );
60 }
61
62 return( temp );
63 }
64
65deflab( n ){
66 /* output something to define the current position as label n */
67 fprintf( outfile, "L%d:\n", n );
68 }
69
70int crslab = 10;
71
72getlab(){
73 /* return a number usable for a label */
74 return( ++crslab );
75 }
76
77efcode(){
78 /* code for the end of a function */
79
80 if( strftn ){ /* copy output (in r0) to caller */
81 register struct symtab *p;
82 register int stlab;
83 register int count;
84 int size;
85
86 p = &stab[curftn];
87
88 deflab( retlab );
89
90 stlab = getlab();
91 printf( " mov $L%d,r1\n", stlab );
92 size = tsize( DECREF(p->stype), p->dimoff, p->sizoff ) / SZCHAR;
93 count = size/2;
94 while( count-- ) {
95 printf( " mov (r0)+,(r1)+\n" );
96 }
97 printf( " mov $L%d,r0\n", stlab );
98 printf( " .bss\nL%d: .=.+%d.\n .text\n", stlab, size );
99 /* turn off strftn flag, so return sequence will be generated */
100 strftn = 0;
101 }
102 branch( retlab );
103 p2bend();
104 }
105
106bfcode( a, n ) int a[]; {
107 /* code for the beginning of a function; a is an array of
108 indices in stab for the arguments; n is the number */
109 register i;
110 register temp;
111 register struct symtab *p;
112 int off;
113
114 locctr( PROG );
115 p = &stab[curftn];
116 defnam( p );
117 temp = p->stype;
118 temp = DECREF(temp);
119 strftn = (temp==STRTY) || (temp==UNIONTY);
120
121 retlab = getlab();
122 if( proflag ){
123 int plab;
124 plab = getlab();
125 printf( " mov $L%d,r0\n", plab );
126 printf( " jsr pc,mcount\n" );
127 printf( " .bss\nL%d: .=.+2\n .text\n", plab );
128 }
129
130 /* routine prolog */
131
132 printf( " jsr r5,csv\n" );
133 /* adjust stack for autos */
134 printf( " sub $.F%d,sp\n", ftnno );
135
136 off = ARGINIT;
137
138 for( i=0; i<n; ++i ){
139 p = &stab[a[i]];
140 if( p->sclass == REGISTER ){
141 temp = p->offset; /* save register number */
142 p->sclass = PARAM; /* forget that it is a register */
143 p->offset = NOOFFSET;
144 oalloc( p, &off );
145 printf( " mov %d.(r5),r%d\n", p->offset/SZCHAR, temp );
146 p->offset = temp; /* remember register number */
147 p->sclass = REGISTER; /* remember that it is a register */
148 }
149 else {
150 if( oalloc( p, &off ) ) cerror( "bad argument" );
151 }
152
153 }
154 }
155
156bccode(){ /* called just before the first executable statment */
157 /* by now, the automatics and register variables are allocated */
158 SETOFF( autooff, SZINT );
159 /* set aside store area offset */
160 p2bbeg( autooff, regvar );
161 }
162
163ejobcode( flag ){
164 /* called just before final exit */
165 /* flag is 1 if errors, 0 if none */
166 }
167
168aobeg(){
169 /* called before removing automatics from stab */
170 }
171
172aocode(p) struct symtab *p; {
173 /* called when automatic p removed from stab */
174 }
175
176aoend(){
177 /* called after removing all automatics from stab */
178 }
179
180defnam( p ) register struct symtab *p; {
181 /* define the current location as the name p->sname */
182
183 if( p->sclass == EXTDEF ){
184 printf( " .globl %s\n", exname( p->sname ) );
185 }
186 if( p->sclass == STATIC && p->slevel>1 ) deflab( p->offset );
187 else printf( "%s:\n", exname( p->sname ) );
188
189 }
190
191bycode( t, i ){
192 /* put byte i+1 in a string */
193
194 i &= 07;
195 if( t < 0 ){ /* end of the string */
196 if( i != 0 ) fprintf( outfile, "\n" );
197 }
198
199 else { /* stash byte t into string */
200 if( i == 0 ) fprintf( outfile, " .byte " );
201 else fprintf( outfile, "," );
202 fprintf( outfile, "%o", t );
203 if( i == 07 ) fprintf( outfile, "\n" );
204 }
205 }
206
207zecode( n ){
208 /* n integer words of zeros */
209 OFFSZ temp;
210 register i;
211
212 if( n <= 0 ) return;
213 printf( " " );
214 for( i=1; i<n; i++ ) {
215 if( i%8 == 0 )
216 printf( "\n " );
217 printf( "0; " );
218 }
219 printf( "0\n" );
220 temp = n;
221 inoff += temp*SZINT;
222 }
223
224fldal( t ) unsigned t; { /* return the alignment of field of type t */
225 uerror( "illegal field type" );
226 return( ALINT );
227 }
228
229fldty( p ) struct symtab *p; { /* fix up type of field p */
230 ;
231 }
232
233where(c){ /* print location of error */
234 /* c is either 'u', 'c', or 'w' */
235 fprintf( stderr, "%s, line %d: ", ftitle, lineno );
236 }
237
238char *tmpname = "/tmp/pcXXXXXX";
239
240main( argc, argv ) char *argv[]; {
241 int dexit();
242 register int c;
243 register int i;
244 int r;
245
246 for( i=1; i<argc; ++i )
247 if( argv[i][0] == '-' && argv[i][1] == 'X' && argv[i][2] == 'p' ) {
248 proflag = 1;
249 }
250
251 mktemp(tmpname);
252 if(signal( SIGHUP, SIG_IGN) != SIG_IGN) signal(SIGHUP, dexit);
253 if(signal( SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, dexit);
254 if(signal( SIGTERM, SIG_IGN) != SIG_IGN) signal(SIGTERM, dexit);
255 tmpfile = fopen( tmpname, "w" );
256
257 r = mainp1( argc, argv );
258
259 tmpfile = freopen( tmpname, "r", tmpfile );
260 if( tmpfile != NULL )
261 while((c=getc(tmpfile)) != EOF )
262 putchar(c);
263 else cerror( "Lost temp file" );
264 unlink(tmpname);
265 return( r );
266 }
267
268dexit( v ) {
269 unlink(tmpname);
270 exit(1);
271 }
272
273genswitch(p,n) register struct sw *p;{
274 /* p points to an array of structures, each consisting
275 of a constant value and a label.
276 The first is >=0 if there is a default label;
277 its value is the label number
278 The entries p[1] to p[n] are the nontrivial cases
279 */
280 register i;
281 register CONSZ j, range;
282 register dlab, swlab;
283
284 range = p[n].sval-p[1].sval;
285
286 if( range>0 && range <= 3*n && n>=4 ){ /* implement a direct switch */
287
288 dlab = p->slab >= 0 ? p->slab : getlab();
289
290 if( p[1].sval ){
291 printf( " sub $" );
292 printf( CONFMT, p[1].sval );
293 printf( ".,r0\n" );
294 }
295
296 /* note that this is a cl; it thus checks
297 for numbers below range as well as out of range.
298 */
299 printf( " cmp r0,$%ld.\n", range );
300 printf( " jhi L%d\n", dlab );
301
302 printf( " asl r0\n" );
303 printf( " jmp *L%d(r0)\n", swlab = getlab() );
304
305 /* output table */
306
307 locctr( ADATA );
308 defalign( ALPOINT );
309 deflab( swlab );
310
311 for( i=1,j=p[1].sval; i<=n; ++j ){
312
313 printf( " L%d\n", ( j == p[i].sval ) ?
314 p[i++].slab : dlab );
315 }
316
317 locctr( PROG );
318
319 if( p->slab< 0 ) deflab( dlab );
320 return;
321
322 }
323
324 /* debugging code */
325
326 /* out for the moment
327 if( n >= 4 ) werror( "inefficient switch: %d, %d", n, (int) (range/n) );
328 */
329
330 /* simple switch code */
331
332 for( i=1; i<=n; ++i ){
333 /* already in r0 */
334
335 printf( " cmp r0,$" );
336 printf( CONFMT, p[i].sval );
337 printf( ".\n jeq L%d\n", p[i].slab );
338 }
339
340 if( p->slab>=0 ) branch( p->slab );
341 }