BSD 3 development
[unix-history] / usr / src / cmd / pcc / local.c
CommitLineData
ba7f559a
BJ
1# include "mfile1"
2extern int eprint();
3
4/* this file contains code which is dependent on the target machine */
5
6NODE *
7cast( p, t ) register NODE *p; TWORD t; {
8 /* cast node p to type t */
9
10 p = buildtree( CAST, block( NAME, NIL, NIL, t, 0, (int)t ), p );
11 p->left->op = FREE;
12 p->op = FREE;
13 return( p->right );
14 }
15
16NODE *
17clocal(p) NODE *p; {
18
19 /* this is called to do local transformations on
20 an expression tree preparitory to its being
21 written out in intermediate code.
22 */
23
24 /* the major essential job is rewriting the
25 automatic variables and arguments in terms of
26 REG and OREG nodes */
27 /* conversion ops which are not necessary are also clobbered here */
28 /* in addition, any special features (such as rewriting
29 exclusive or) are easily handled here as well */
30
31 register struct symtab *q;
32 register NODE *r;
33 register o;
34 register m, ml;
35
36 switch( o = p->op ){
37
38 case NAME:
39 if( p->rval < 0 ) { /* already processed; ignore... */
40 return(p);
41 }
42 q = &stab[p->rval];
43 switch( q->sclass ){
44
45 case AUTO:
46 case PARAM:
47 /* fake up a structure reference */
48 r = block( REG, NIL, NIL, PTR+STRTY, 0, 0 );
49 r->lval = 0;
50 r->rval = (q->sclass==AUTO?STKREG:ARGREG);
51 p = stref( block( STREF, r, p, 0, 0, 0 ) );
52 break;
53
54 case ULABEL:
55 case LABEL:
56 case STATIC:
57 if( q->slevel == 0 ) break;
58 p->lval = 0;
59 p->rval = -q->offset;
60 break;
61
62 case REGISTER:
63 p->op = REG;
64 p->lval = 0;
65 p->rval = q->offset;
66 break;
67
68 }
69 break;
70
71 case PCONV:
72 /* do pointer conversions for char and longs */
73 ml = p->left->type;
74 if( ( ml==CHAR || ml==UCHAR || ml==SHORT || ml==USHORT ) && p->left->op != ICON ) break;
75
76 /* pointers all have the same representation; the type is inherited */
77
78 inherit:
79 p->left->type = p->type;
80 p->left->cdim = p->cdim;
81 p->left->csiz = p->csiz;
82 p->op = FREE;
83 return( p->left );
84
85 case SCONV:
86 m = (p->type == FLOAT || p->type == DOUBLE );
87 ml = (p->left->type == FLOAT || p->left->type == DOUBLE );
88 if( m != ml ) break;
89
90 /* now, look for conversions downwards */
91
92 m = p->type;
93 ml = p->left->type;
94 if( p->left->op == ICON ){ /* simulate the conversion here */
95 CONSZ val;
96 val = p->left->lval;
97 switch( m ){
98 case CHAR:
99 p->left->lval = (char) val;
100 break;
101 case UCHAR:
102 p->left->lval = val & 0XFF;
103 break;
104 case USHORT:
105 p->left->lval = val & 0XFFFFL;
106 break;
107 case SHORT:
108 p->left->lval = (short)val;
109 break;
110 case UNSIGNED:
111 p->left->lval = val & 0xFFFFFFFFL;
112 break;
113 case INT:
114 p->left->lval = (int)val;
115 break;
116 }
117 p->left->type = m;
118 }
119 else {
120 /* meaningful ones are conversion of int to char, int to short,
121 and short to char, and unsigned version of them */
122 if( m==CHAR || m==UCHAR ){
123 if( ml!=CHAR && ml!= UCHAR ) break;
124 }
125 else if( m==SHORT || m==USHORT ){
126 if( ml!=CHAR && ml!=UCHAR && ml!=SHORT && ml!=USHORT ) break;
127 }
128 }
129
130 /* clobber conversion */
131 if( tlen(p) == tlen(p->left) ) goto inherit;
132 p->op = FREE;
133 return( p->left ); /* conversion gets clobbered */
134
135 case PVCONV:
136 case PMCONV:
137 if( p->right->op != ICON ) cerror( "bad conversion", 0);
138 p->op = FREE;
139 return( buildtree( o==PMCONV?MUL:DIV, p->left, p->right ) );
140
141 case RS:
142 case ASG RS:
143 /* convert >> to << with negative shift count */
144 /* only if type of left operand is not unsigned */
145 if( ISUNSIGNED(p->left->type) ) break;
146 p->right = buildtree( UNARY MINUS, p->right, NIL );
147 if( p->op == RS ) p->op = LS;
148 else p->op = ASG LS;
149 break;
150
151 case FLD:
152 if( p->left->op == UNARY MUL && (r=p->left->left)->op == PCONV)
153 if( r->left->op == PLUS || r->left->op == MINUS )
154 if( ISPTR(r->type) ) {
155 if( ISUNSIGNED(p->left->type) )
156 p->left->type = UCHAR;
157 else
158 p->left->type = CHAR;
159 }
160 break;
161 }
162
163 return(p);
164 }
165
166andable( p ) NODE *p; {
167 return(1); /* all names can have & taken on them */
168 }
169
170cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */
171 autooff = AUTOINIT;
172 }
173
174cisreg( t ) TWORD t; { /* is an automatic variable of type t OK for a register variable */
175
176 if( t==INT || t==UNSIGNED || t==LONG || t==ULONG /* tbl */
177 || t==CHAR || t==UCHAR || t==SHORT || t==USHORT /* tbl */
178 || t==FLOAT || t==DOUBLE || ISPTR(t)) return(1); /* tbl */
179 return(0);
180 }
181
182NODE *
183offcon( off, t, d, s ) OFFSZ off; TWORD t; {
184
185 /* return a node, for structure references, which is suitable for
186 being added to a pointer of type t, in order to be off bits offset
187 into a structure */
188
189 register NODE *p;
190
191 /* t, d, and s are the type, dimension offset, and sizeoffset */
192 /* in general they are necessary for offcon, but not on H'well */
193
194 p = bcon(0);
195 p->lval = off/SZCHAR;
196 return(p);
197
198 }
199
200
201static inwd /* current bit offsed in word */;
202static word /* word being built from fields */;
203
204incode( p, sz ) register NODE *p; {
205
206 /* generate initialization code for assigning a constant c
207 to a field of width sz */
208 /* we assume that the proper alignment has been obtained */
209 /* inoff is updated to have the proper final value */
210 /* we also assume sz < SZINT */
211
212 if((sz+inwd) > SZINT) cerror("incode: field > int");
213 word |= ((unsigned)(p->lval<<(32-sz))) >> (32-sz-inwd);
214 inwd += sz;
215 inoff += sz;
216 if(inoff%SZINT == 0) {
217 printf( " .long 0x%x\n", word);
218 word = inwd = 0;
219 }
220 }
221
222fincode( d, sz ) double d; {
223 /* output code to initialize space of size sz to the value d */
224 /* the proper alignment has been obtained */
225 /* inoff is updated to have the proper final value */
226 /* on the target machine, write it out in octal! */
227
228
229 printf(" %s 0%c%.20e\n", sz == SZDOUBLE ? ".double" : ".float",
230 sz == SZDOUBLE ? 'd' : 'f', d);
231 inoff += sz;
232 }
233
234cinit( p, sz ) NODE *p; {
235 /* arrange for the initialization of p into a space of
236 size sz */
237 /* the proper alignment has been opbtained */
238 /* inoff is updated to have the proper final value */
239 ecode( p );
240 inoff += sz;
241 }
242
243vfdzero( n ){ /* define n bits of zeros in a vfd */
244
245 if( n <= 0 ) return;
246
247 inwd += n;
248 inoff += n;
249 if( inoff%ALINT ==0 ) {
250 printf( " .long 0x%x\n", word );
251 word = inwd = 0;
252 }
253 }
254
255char *
256exname( p ) char *p; {
257 /* make a name look like an external name in the local machine */
258
259 static char text[NCHNAM+1];
260
261 register i;
262
263 text[0] = '_';
264 for( i=1; *p&&i<NCHNAM; ++i ){
265 text[i] = *p++;
266 }
267
268 text[i] = '\0';
269 text[NCHNAM] = '\0'; /* truncate */
270
271 return( text );
272 }
273
274ctype( type ){ /* map types which are not defined on the local machine */
275 switch( BTYPE(type) ){
276
277 case LONG:
278 MODTYPE(type,INT);
279 break;
280
281 case ULONG:
282 MODTYPE(type,UNSIGNED);
283 }
284 return( type );
285 }
286
287noinit( t ) { /* curid is a variable which is defined but
288 is not initialized (and not a function );
289 This routine returns the stroage class for an uninitialized declaration */
290
291 return(EXTERN);
292
293 }
294
295commdec( id ){ /* make a common declaration for id, if reasonable */
296 register struct symtab *q;
297 OFFSZ off, tsize();
298
299 q = &stab[id];
300 printf( " .comm %s,", exname( q->sname ) );
301 off = tsize( q->stype, q->dimoff, q->sizoff );
302 printf( CONFMT, off/SZCHAR );
303 printf( "\n" );
304 }
305
306isitlong( cb, ce ){ /* is lastcon to be long or short */
307 /* cb is the first character of the representation, ce the last */
308
309 if( ce == 'l' || ce == 'L' ||
310 lastcon >= (1L << (SZINT-1) ) ) return (1);
311 return(0);
312 }
313
314
315isitfloat( s ) char *s; {
316 double atof();
317 dcon = atof(s);
318 return( FCON );
319 }
320
321ecode( p ) NODE *p; {
322
323 /* walk the tree and write out the nodes.. */
324
325 if( nerrors ) return;
326 p2tree( p );
327 p2compile( p );
328 }
329
330#include "a.out.h"
331int ddebug;
332int gdebug;
333
334
335outstab(p)
336struct symtab *p; {
337 register TWORD ptype;
338 register char *pname;
339 register char pclass;
340 register int poffset;
341
342 if (!gdebug) return;
343
344 ptype = p->stype;
345 pname = p->sname;
346 pclass = p->sclass;
347 poffset = p->offset;
348
349 if (ISFTN(ptype)) {
350 return;
351 }
352
353 switch (pclass) {
354
355 case AUTO:
356 pstab(pname, N_LSYM);
357 printf("0,%d,%d\n", ptype, (-poffset)/SZCHAR);
358 poffs(p);
359 return;
360
361 case EXTDEF:
362 case EXTERN:
363 pstab(pname, N_GSYM);
364 printf("0,%d,0\n", ptype);
365 poffs(p);
366 return;
367
368 case STATIC:
369 pstab(pname, N_STSYM);
370 if (p->slevel > 1) {
371 printf("0,%d,L%d\n", ptype, poffset);
372 } else {
373 printf("0,%d,%s\n", ptype, exname(pname));
374 }
375 poffs(p);
376 return;
377
378 case REGISTER:
379 pstab(pname, N_RSYM);
380 printf("0,%d,%d\n", ptype, poffset);
381 poffs(p);
382 return;
383
384 case MOS:
385 case MOU:
386 pstab(pname, N_SSYM);
387 printf("0,%d,%d\n", ptype, poffset/SZCHAR);
388 poffs(p);
389 return;
390
391 case PARAM:
392 /* parameter stab entries are processed in dclargs() */
393 return;
394
395 default:
396 if (ddebug) printf(" No .stab for %.8s\n", pname);
397 }
398}
399
400pstab(name, type)
401char *name;
402 int type;
403{
404 register int i;
405 register char c;
406 if (!gdebug) return;
407#ifdef ASSTRINGS
408 if ( name[0] == '\0')
409 printf("\t.stabn\t");
410 else
411 printf("\t.stabs\t\"%.8s\", ", name);
412#else
413
414 printf(" .stab ");
415 for(i=0; i<8; i++)
416 if (c = name[i]) printf("'%c,", c);
417 else printf("0,");
418#endif
419 printf("0%o,", type);
420}
421
422#ifdef STABDOT
423pstabdot(type, value)
424 int type;
425 int value;
426{
427 if ( ! gdebug) return;
428 printf("\t.stabd\t");
429 printf("0%o,0,0%o\n",type, value);
430}
431#endif
432
433poffs(p)
434register struct symtab *p; {
435 int s;
436 if (!gdebug) return;
437 if ((s = dimtab[p->sizoff]/SZCHAR) > 1) {
438 pstab(p->sname, N_LENG);
439 printf("1,0,%d\n", s);
440 }
441}
442
443char NULLNAME[8];
444int labelno;
445int fdefflag;
446
447psline() {
448 static int lastlineno;
449 register char *cp, *cq;
450 register int i;
451
452 if (!gdebug) return;
453
454 cq = ititle;
455 cp = ftitle;
456
457 while ( *cq ) if ( *cp++ != *cq++ ) goto neq;
458 if ( *cp == '\0' ) goto eq;
459
460neq: for (i=0; i<100; i++)
461 ititle[i] = '\0';
462 cp = ftitle;
463 cq = ititle;
464 while ( *cp )
465 *cq++ = *cp++;
466 *cq = '\0';
467 *--cq = '\0';
468 for ( cp = ititle+1; *(cp-1); cp += 8 ) {
469 /*
470 * We use the old style stab to introduce the
471 * name of the file. This is the only place
472 * where we could use a stab, with the last
473 * expression the '.', but this is also the only
474 * place where the first argument to the stab is
475 * a string (namely the name of the file).
476 */
477 pstab(cp, N_SOL);
478 if (gdebug) printf("0,0,LL%d\n", labelno);
479 }
480 *cq = '"';
481 printf("LL%d:\n", labelno++);
482
483eq: if (lineno == lastlineno) return;
484 lastlineno = lineno;
485
486 if (fdefflag) {
487#ifdef STABDOT
488 pstabdot(N_SLINE, lineno);
489#else
490 pstab(NULLNAME, N_SLINE);
491 printf("0,%d,LL%d\n", lineno, labelno);
492 printf("LL%d:\n", labelno++);
493#endif
494 }
495 }
496
497plcstab(level) {
498 if (!gdebug) return;
499#ifdef STABDOT
500 pstabdot(N_LBRAC, level);
501#else
502 pstab(NULLNAME, N_LBRAC);
503 printf("0,%d,LL%d\n", level, labelno);
504 printf("LL%d:\n", labelno++);
505#endif
506 }
507
508prcstab(level) {
509 if (!gdebug) return;
510#ifdef STABDOT
511 pstabdot(N_RBRAC, level);
512#else
513 pstab(NULLNAME, N_RBRAC);
514 printf("0,%d,LL%d\n", level, labelno);
515 printf("LL%d:\n", labelno++);
516#endif
517 }
518
519pfstab(sname)
520char *sname; {
521 if (!gdebug) return;
522 pstab(sname, N_FUN);
523 printf("0,%d,_%.7s\n", lineno, sname);
524}
525
526#ifndef ONEPASS
527tlen(p) NODE *p;
528{
529 switch(p->type) {
530 case CHAR:
531 case UCHAR:
532 return(1);
533
534 case SHORT:
535 case USHORT:
536 return(2);
537
538 case DOUBLE:
539 return(8);
540
541 default:
542 return(4);
543 }
544 }
545#endif
546
547
548