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