purge as many printf calls as possible
[unix-history] / usr / src / old / pcc / ccom.tahoe / local.c
CommitLineData
b4204852 1#ifndef lint
895241c8 2static char sccsid[] = "@(#)local.c 1.3 (Berkeley) %G%";
b4204852
SL
3#endif
4
7b1562c4 5# include "pass1.h"
b4204852
SL
6
7/* this file contains code which is dependent on the target machine */
8
9NODE *
10clocal(p) register NODE *p; {
11
12 /* this is called to do local transformations on
13 an expression tree preparitory to its being
14 written out in intermediate code.
15 */
16
17 /* the major essential job is rewriting the
18 automatic variables and arguments in terms of
19 REG and OREG nodes */
20 /* conversion ops which are not necessary are also clobbered here */
21 /* in addition, any special features (such as rewriting
22 exclusive or) are easily handled here as well */
23
24 register struct symtab *q;
25 register NODE *r;
26 register int o;
27 register int m, ml;
28
29 switch( o = p->in.op ){
30
31 case NAME:
32 if( p->tn.rval < 0 ) { /* already processed; ignore... */
33 return(p);
34 }
35 q = &stab[p->tn.rval];
36 switch( q->sclass ){
37
38 case AUTO:
39 case PARAM:
40 /* fake up a structure reference */
41 r = block( REG, NIL, NIL, PTR+STRTY, 0, 0 );
42 r->tn.lval = 0;
43 r->tn.rval = STKREG;
44 p = stref( block( STREF, r, p, 0, 0, 0 ) );
45 break;
46
47 case ULABEL:
48 case LABEL:
49 case STATIC:
50 if( q->slevel == 0 ) break;
51 p->tn.lval = 0;
52 p->tn.rval = -q->offset;
53 break;
54
55 case REGISTER:
56 p->in.op = REG;
57 p->tn.lval = 0;
58 p->tn.rval = q->offset;
59#ifdef REG_CHAR
60 m = p->in.type;
61 if( m==CHAR || m==SHORT )
62 p->in.type = INT;
63 else if( m==UCHAR || m==USHORT )
64 p->in.type = UNSIGNED;
65#endif
66 break;
67
68 }
69 break;
70
71 case LT:
72 case LE:
73 case GT:
74 case GE:
75 if( ISPTR( p->in.left->in.type ) || ISPTR( p->in.right->in.type ) ){
76 p->in.op += (ULT-LT);
77 }
78 break;
79
80 case PCONV:
81 /* do pointer conversions for char and longs */
82 ml = p->in.left->in.type;
83 if( ( ml==CHAR || ml==UCHAR || ml==SHORT || ml==USHORT ) && p->in.left->in.op != ICON ) break;
84
85 /* pointers all have the same representation; the type is inherited */
86
87 inherit:
88 p->in.left->in.type = p->in.type;
89 p->in.left->fn.cdim = p->fn.cdim;
90 p->in.left->fn.csiz = p->fn.csiz;
91 p->in.op = FREE;
92 return( p->in.left );
93
94 case SCONV:
95 m = p->in.type;
96 ml = p->in.left->in.type;
97 if(m == FLOAT || m == DOUBLE) {
98 if(p->in.left->in.op==SCONV &&
99 (ml == FLOAT || ml == DOUBLE) &&
100 p->in.left->in.left->in.type==m) {
101 p->in.op = p->in.left->in.op = FREE;
102 return(p->in.left->in.left);
103 }
104 if(p->in.left->in.op==FCON)
105 goto inherit;
106 break;
107 }
108 if(ml == FLOAT || ml == DOUBLE){
109 if (p->in.left->in.op == FCON){
110 p->in.left->in.op = FREE;
111 p->in.op = ICON;
7b1562c4 112 p->tn.lval = p->in.left->fpn.fval;
b4204852
SL
113 p->tn.rval = NONAME;
114 return(p);
115 }
116 break;
117 }
118 /* now, look for conversions downwards */
119
120 if( p->in.left->in.op == ICON ){ /* simulate the conversion here */
121 CONSZ val;
122 val = p->in.left->tn.lval;
123 switch( m ){
124 case CHAR:
125 p->in.left->tn.lval = (char) val;
126 break;
127 case UCHAR:
128 p->in.left->tn.lval = val & 0XFF;
129 break;
130 case USHORT:
131 p->in.left->tn.lval = val & 0XFFFFL;
132 break;
133 case SHORT:
134 p->in.left->tn.lval = (short)val;
135 break;
136 case UNSIGNED:
137 p->in.left->tn.lval = val & 0xFFFFFFFFL;
138 break;
139 case INT:
140 p->in.left->tn.lval = (int)val;
141 break;
142 }
143 p->in.left->in.type = m;
144 }
145 else {
146 /* meaningful ones are conversion of int to char, int to short,
147 and short to char, and unsigned versions thereof */
148 if( m==CHAR || m==UCHAR ){
149 if( ml!=CHAR && ml!= UCHAR ) break;
150 }
151 else if( m==SHORT || m==USHORT ){
152 if( ml!=CHAR && ml!=UCHAR && ml!=SHORT && ml!=USHORT ) break;
153 }
154 }
155
156 /* clobber conversion */
157 if( tlen(p) == tlen(p->in.left) ) goto inherit;
158 p->in.op = FREE;
159 return( p->in.left ); /* conversion gets clobbered */
160
161 case QUEST: /* the right side should be COLON */
162 if((r = p->in.right)->in.op == SCONV) {
163 p->in.right = r->in.left;
164 p->in.type = r->in.left->in.type;
165 r->in.left = p;
166 return(r);
167 }
168 return(p);
169
170 case PVCONV:
171 case PMCONV:
172 if( p->in.right->in.op != ICON ) cerror( "bad conversion", 0);
173 p->in.op = FREE;
174 return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) );
175
176 case FLD:
177 /* make sure that the second pass does not make the
178 descendant of a FLD operator into a doubly indexed OREG */
179
180 if( p->in.left->in.op == UNARY MUL
181 && (r=p->in.left->in.left)->in.op == PCONV)
182 if( r->in.left->in.op == PLUS || r->in.left->in.op == MINUS )
183 if( ISPTR(r->in.type) ) {
184 if( ISUNSIGNED(p->in.left->in.type) )
185 p->in.left->in.type = UNSIGNED;
186 else
187 p->in.left->in.type = INT;
188 }
189 break;
7b1562c4
SL
190 case FORTCALL: /* arg must be FLOAT */
191 if((r = p->in.right)->in.type != FLOAT)
192 p->in.right = clocal(makety(r, FLOAT, 0, FLOAT));
193 return(p);
194 }
b4204852
SL
195
196 /* if both sides are FLOAT, so is the op */
197 if(optype(o)!=LTYPE && p->in.left->in.type==DOUBLE &&
198 (o==UNARY MINUS || optype(o)==BITYPE && p->in.right->in.type==DOUBLE)) {
199 r = p->in.left;
200 if(r->in.op==SCONV && r->in.left->in.type==FLOAT) {
201 if(optype(o)==BITYPE) {
202 r = p->in.right;
203 if(r->in.op==SCONV && r->in.left->in.type==FLOAT) {
204 r->in.op = FREE;
205 p->in.right = r->in.left;
206 } else if(r->in.op==FCON)
207 r->in.type = FLOAT;
208 else
209 return(p);
210 }
211 r = p->in.left;
212 p->in.left = r->in.left;
213 } else if(optype(o)==BITYPE && r->in.op==FCON) {
214 r = p->in.right;
215 if(!(r->in.op==SCONV && r->in.left->in.type==FLOAT))
216 return(p);
217 p->in.right = r->in.left;
218 p->in.left->in.type = FLOAT;
219 } else
220 return(p);
221 if(p->in.type==DOUBLE) {
222 p->in.type = FLOAT;
223 r->in.left = p;
224 return(r);
225 } else { /* usually logop */
226 r->in.op = FREE;
227 return(p);
228 }
229 }
230 return(p);
231}
232
233andable( p ) NODE *p; {
234 return(1); /* all names can have & taken on them */
235 }
236
237cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */
238 autooff = AUTOINIT;
239 }
240
241cisreg( t ) TWORD t; { /* is an automatic variable of type t OK for a register variable */
242
243 if( t==INT || t==UNSIGNED || t==LONG || t==ULONG /* tbl */
244#ifdef REG_CHAR
245 || t==CHAR || t==UCHAR || t==SHORT || t==USHORT /* tbl */
246#endif
247 || ISPTR(t)) return (1); /* wnj */
248 return(0);
249 }
250
251NODE *
252offcon( off, t, d, s ) OFFSZ off; TWORD t; {
253
254 /* return a node, for structure references, which is suitable for
255 being added to a pointer of type t, in order to be off bits offset
256 into a structure */
257
258 register NODE *p;
259
260 /* t, d, and s are the type, dimension offset, and sizeoffset */
261 /* in general they are necessary for offcon, but not on H'well */
262
263 p = bcon(0);
264 p->tn.lval = off/SZCHAR;
265 return(p);
266
267 }
268
269
270static inwd /* current bit offsed in word */;
271static CONSZ word /* word being built from fields */;
272
273incode( p, sz ) register NODE *p; {
274
275 /* generate initialization code for assigning a constant c
276 to a field of width sz */
277 /* we assume that the proper alignment has been obtained */
278 /* inoff is updated to have the proper final value */
279 /* we also assume sz < SZINT */
280
281 inwd += sz;
282 if(inwd > SZINT) cerror("incode: field > int");
283 word |= (p->tn.lval&((1L<<sz)-1)) << (SZINT-inwd);
284 inoff += sz;
285 if(inoff%SZINT == 0) {
7b1562c4 286 printf( " .long 0x%X\n", word);
b4204852
SL
287 word = inwd = 0;
288 }
289 }
290
b4204852
SL
291fincode( d, sz ) double d; register int sz; {
292 /*
293 * output code to initialize space of size sz to the value d
294 * the proper alignment has been obtained
7b1562c4 295 * inoff is updated to have the proper final value.
b4204852
SL
296 */
297
298 register struct sh4 {
299 unsigned short sh[4];
300 } *x;
b4204852
SL
301 float f;
302
303 if(sz == SZFLOAT) { /* force rounding */
304 f = d;
305 d = f;
306 }
b4204852
SL
307
308 x = (struct sh4 *)&d;
309 printf(" .long 0x%04x%04x", x->sh[0], x->sh[1]);
b4204852
SL
310 if(sz == SZDOUBLE) {
311 printf(", 0x%04x%04x", x->sh[2], x->sh[3]);
312 printf(" # .double %.17g\n", d);
313 } else
314 printf(" # .float %.8g\n", d);
315 inoff += sz;
b4204852
SL
316 }
317
318cinit( p, sz ) NODE *p; {
7b1562c4
SL
319 NODE *l;
320
321 /*
322 * as a favor (?) to people who want to write
323 * int i = 9600/134.5;
324 * we will, under the proper circumstances, do
325 * a coersion here.
326 */
327 switch (p->in.type) {
328 case INT:
329 case UNSIGNED:
330 l = p->in.left;
331 if (l->in.op != SCONV ||
332 (l->in.left->tn.op != DCON && l->in.left->tn.op != FCON))
333 break;
334 l->in.op = FREE;
335 l = l->in.left;
336 l->tn.lval = l->tn.op == DCON ? (long)(l->dpn.dval) :
337 (long)(l->fpn.fval);
338 l->tn.rval = NONAME;
339 l->tn.op = ICON;
340 l->tn.type = INT;
341 p->in.left = l;
342 break;
343 }
b4204852
SL
344 /* arrange for the initialization of p into a space of
345 size sz */
346 /* the proper alignment has been opbtained */
347 /* inoff is updated to have the proper final value */
348 ecode( p );
349 inoff += sz;
350 }
351
352vfdzero( n ){ /* define n bits of zeros in a vfd */
353
354 if( n <= 0 ) return;
355
356 inwd += n;
357 inoff += n;
358 if( inoff%ALINT ==0 ) {
7b1562c4 359 printf( " .long 0x%X\n", word );
b4204852
SL
360 word = inwd = 0;
361 }
362 }
363
364char *
365exname( p ) char *p; {
366 /* make a name look like an external name in the local machine */
367
368#ifndef FLEXNAMES
369 static char text[NCHNAM+1];
370#else
371 static char text[BUFSIZ+1];
372#endif
373
374 register int i;
375
376 text[0] = '_';
377#ifndef FLEXNAMES
7b1562c4 378 for( i=1; *p&&i<NCHNAM; ++i )
b4204852 379#else
7b1562c4 380 for( i=1; *p; ++i )
b4204852
SL
381#endif
382 text[i] = *p++;
b4204852
SL
383
384 text[i] = '\0';
385#ifndef FLEXNAMES
386 text[NCHNAM] = '\0'; /* truncate */
387#endif
388
389 return( text );
390 }
391
392ctype( type )TWORD type;{ /* map types which are not defined on the local machine */
393 switch( BTYPE(type) ){
394
395 case LONG:
396 MODTYPE(type,INT);
397 break;
398
399 case ULONG:
400 MODTYPE(type,UNSIGNED);
401 }
402 return( type );
403 }
404
405noinit() { /* curid is a variable which is defined but
406 is not initialized (and not a function );
407 This routine returns the stroage class for an uninitialized declaration */
408
409 return(EXTERN);
410
411 }
412
413commdec( id ){ /* make a common declaration for id, if reasonable */
414 register struct symtab *q;
415 OFFSZ off, tsize();
416
417 q = &stab[id];
418 printf( " .comm %s,", exname( q->sname ) );
419 off = tsize( q->stype, q->dimoff, q->sizoff );
895241c8 420 printf( "%d\n" /*CONFMT*/, off/SZCHAR );
b4204852
SL
421 }
422
7b1562c4
SL
423prtdcon(p)
424 register NODE *p;
425{
426 register int o = p->in.op;
427 int i;
428
429 if (o != DCON && o != FCON)
430 return;
431 /*
432 * Clobber constants of value zero so
433 * we can generate more efficient code.
434 */
435 if ((o == DCON && p->dpn.dval == 0) ||
436 (o == FCON && p->fpn.fval == 0)) {
437 p->in.op = ICON;
438 p->tn.rval = NONAME;
439 return;
440 }
441 locctr(DATA);
442 defalign(o == DCON ? ALDOUBLE : ALFLOAT);
443 deflab(i = getlab());
444 if (o == FCON)
445 fincode(p->fpn.fval, SZFLOAT);
446 else
447 fincode(p->dpn.dval, SZDOUBLE);
448 p->tn.lval = 0;
449 p->tn.rval = -i;
450 p->in.type = (o == DCON ? DOUBLE : FLOAT);
451 p->in.op = NAME;
452}
b4204852
SL
453
454isitfloat( s ) char *s; {
7b1562c4
SL
455 union cvt {
456 double d;
457 int n[2];
458 } cvt;
b4204852 459 double atof();
7b1562c4
SL
460
461 /* avoid floating point exception for double -> float conversions */
462 dcon = cvt.d = atof(s);
463 if( cvt.n[1] == 0 ){
464 fcon = dcon;
465 return( FCON );
466 }
467 return( DCON );
b4204852
SL
468 }
469
470ecode( p ) NODE *p; {
471
472 /* walk the tree and write out the nodes.. */
473
474 if( nerrors ) return;
475 p2tree( p );
476 p2compile( p );
477 }
478
479#ifndef ONEPASS
480tlen(p) NODE *p;
481{
482 switch(p->in.type) {
483 case CHAR:
484 case UCHAR:
485 return(1);
486
487 case SHORT:
488 case USHORT:
489 return(2);
490
491 case DOUBLE:
492 return(8);
493
494 default:
495 return(4);
496 }
497 }
498#endif