utah rcsid 1.3 87/04/17 21:32:02: Oops -- we still want to clobber constant
[unix-history] / usr / src / old / pcc / ccom.tahoe / local.c
CommitLineData
b4204852 1#ifndef lint
8b1d4f4a 2static char sccsid[] = "@(#)local.c 1.7 (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 &&
d55e09a3 99 ml == DOUBLE &&
b4204852
SL
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
b6f456ab 120 if( p->in.left->in.op == ICON ){ /* simulate the conversion here */
b4204852
SL
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;
9ecc5499
DS
144 }
145#ifdef notdef
146 else if (tlen(p) == tlen(p->in.left))
b6f456ab 147 goto inherit;
8b1d4f4a
DS
148#else
149 else break;
150#endif
b4204852 151 /* clobber conversion */
b4204852
SL
152 p->in.op = FREE;
153 return( p->in.left ); /* conversion gets clobbered */
b6f456ab 154 break;
b4204852
SL
155
156 case QUEST: /* the right side should be COLON */
157 if((r = p->in.right)->in.op == SCONV) {
158 p->in.right = r->in.left;
159 p->in.type = r->in.left->in.type;
160 r->in.left = p;
161 return(r);
162 }
163 return(p);
164
165 case PVCONV:
166 case PMCONV:
167 if( p->in.right->in.op != ICON ) cerror( "bad conversion", 0);
168 p->in.op = FREE;
169 return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) );
170
171 case FLD:
172 /* make sure that the second pass does not make the
173 descendant of a FLD operator into a doubly indexed OREG */
174
175 if( p->in.left->in.op == UNARY MUL
176 && (r=p->in.left->in.left)->in.op == PCONV)
177 if( r->in.left->in.op == PLUS || r->in.left->in.op == MINUS )
178 if( ISPTR(r->in.type) ) {
179 if( ISUNSIGNED(p->in.left->in.type) )
180 p->in.left->in.type = UNSIGNED;
181 else
182 p->in.left->in.type = INT;
183 }
184 break;
7b1562c4
SL
185 case FORTCALL: /* arg must be FLOAT */
186 if((r = p->in.right)->in.type != FLOAT)
187 p->in.right = clocal(makety(r, FLOAT, 0, FLOAT));
188 return(p);
189 }
b4204852
SL
190
191 /* if both sides are FLOAT, so is the op */
192 if(optype(o)!=LTYPE && p->in.left->in.type==DOUBLE &&
193 (o==UNARY MINUS || optype(o)==BITYPE && p->in.right->in.type==DOUBLE)) {
194 r = p->in.left;
195 if(r->in.op==SCONV && r->in.left->in.type==FLOAT) {
196 if(optype(o)==BITYPE) {
197 r = p->in.right;
198 if(r->in.op==SCONV && r->in.left->in.type==FLOAT) {
199 r->in.op = FREE;
200 p->in.right = r->in.left;
201 } else if(r->in.op==FCON)
202 r->in.type = FLOAT;
203 else
204 return(p);
205 }
206 r = p->in.left;
207 p->in.left = r->in.left;
208 } else if(optype(o)==BITYPE && r->in.op==FCON) {
209 r = p->in.right;
210 if(!(r->in.op==SCONV && r->in.left->in.type==FLOAT))
211 return(p);
212 p->in.right = r->in.left;
213 p->in.left->in.type = FLOAT;
214 } else
215 return(p);
216 if(p->in.type==DOUBLE) {
217 p->in.type = FLOAT;
218 r->in.left = p;
219 return(r);
220 } else { /* usually logop */
221 r->in.op = FREE;
222 return(p);
223 }
224 }
225 return(p);
226}
227
228andable( p ) NODE *p; {
229 return(1); /* all names can have & taken on them */
230 }
231
232cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */
233 autooff = AUTOINIT;
234 }
235
236cisreg( t ) TWORD t; { /* is an automatic variable of type t OK for a register variable */
237
238 if( t==INT || t==UNSIGNED || t==LONG || t==ULONG /* tbl */
239#ifdef REG_CHAR
240 || t==CHAR || t==UCHAR || t==SHORT || t==USHORT /* tbl */
241#endif
d55e09a3 242 || ISPTR(t) || t == FLOAT) return (1); /* wnj */
b4204852
SL
243 return(0);
244 }
245
246NODE *
247offcon( off, t, d, s ) OFFSZ off; TWORD t; {
248
249 /* return a node, for structure references, which is suitable for
250 being added to a pointer of type t, in order to be off bits offset
251 into a structure */
252
253 register NODE *p;
254
255 /* t, d, and s are the type, dimension offset, and sizeoffset */
256 /* in general they are necessary for offcon, but not on H'well */
257
258 p = bcon(0);
259 p->tn.lval = off/SZCHAR;
260 return(p);
261
262 }
263
264
265static inwd /* current bit offsed in word */;
266static CONSZ word /* word being built from fields */;
267
268incode( p, sz ) register NODE *p; {
269
270 /* generate initialization code for assigning a constant c
271 to a field of width sz */
272 /* we assume that the proper alignment has been obtained */
273 /* inoff is updated to have the proper final value */
274 /* we also assume sz < SZINT */
275
276 inwd += sz;
277 if(inwd > SZINT) cerror("incode: field > int");
278 word |= (p->tn.lval&((1L<<sz)-1)) << (SZINT-inwd);
279 inoff += sz;
280 if(inoff%SZINT == 0) {
7b1562c4 281 printf( " .long 0x%X\n", word);
b4204852
SL
282 word = inwd = 0;
283 }
284 }
285
b4204852
SL
286fincode( d, sz ) double d; register int sz; {
287 /*
288 * output code to initialize space of size sz to the value d
289 * the proper alignment has been obtained
7b1562c4 290 * inoff is updated to have the proper final value.
b4204852
SL
291 */
292
293 register struct sh4 {
294 unsigned short sh[4];
295 } *x;
b4204852
SL
296 float f;
297
298 if(sz == SZFLOAT) { /* force rounding */
299 f = d;
300 d = f;
301 }
b4204852
SL
302
303 x = (struct sh4 *)&d;
304 printf(" .long 0x%04x%04x", x->sh[0], x->sh[1]);
b4204852
SL
305 if(sz == SZDOUBLE) {
306 printf(", 0x%04x%04x", x->sh[2], x->sh[3]);
307 printf(" # .double %.17g\n", d);
308 } else
309 printf(" # .float %.8g\n", d);
310 inoff += sz;
b4204852
SL
311 }
312
313cinit( p, sz ) NODE *p; {
7b1562c4
SL
314 NODE *l;
315
316 /*
317 * as a favor (?) to people who want to write
318 * int i = 9600/134.5;
319 * we will, under the proper circumstances, do
320 * a coersion here.
321 */
322 switch (p->in.type) {
323 case INT:
324 case UNSIGNED:
325 l = p->in.left;
326 if (l->in.op != SCONV ||
327 (l->in.left->tn.op != DCON && l->in.left->tn.op != FCON))
328 break;
329 l->in.op = FREE;
330 l = l->in.left;
331 l->tn.lval = l->tn.op == DCON ? (long)(l->dpn.dval) :
332 (long)(l->fpn.fval);
333 l->tn.rval = NONAME;
334 l->tn.op = ICON;
335 l->tn.type = INT;
336 p->in.left = l;
337 break;
338 }
b4204852
SL
339 /* arrange for the initialization of p into a space of
340 size sz */
341 /* the proper alignment has been opbtained */
342 /* inoff is updated to have the proper final value */
343 ecode( p );
344 inoff += sz;
345 }
346
347vfdzero( n ){ /* define n bits of zeros in a vfd */
348
349 if( n <= 0 ) return;
350
351 inwd += n;
352 inoff += n;
353 if( inoff%ALINT ==0 ) {
7b1562c4 354 printf( " .long 0x%X\n", word );
b4204852
SL
355 word = inwd = 0;
356 }
357 }
358
359char *
360exname( p ) char *p; {
361 /* make a name look like an external name in the local machine */
362
363#ifndef FLEXNAMES
364 static char text[NCHNAM+1];
365#else
366 static char text[BUFSIZ+1];
367#endif
368
369 register int i;
370
371 text[0] = '_';
372#ifndef FLEXNAMES
7b1562c4 373 for( i=1; *p&&i<NCHNAM; ++i )
b4204852 374#else
7b1562c4 375 for( i=1; *p; ++i )
b4204852
SL
376#endif
377 text[i] = *p++;
b4204852
SL
378
379 text[i] = '\0';
380#ifndef FLEXNAMES
381 text[NCHNAM] = '\0'; /* truncate */
382#endif
383
384 return( text );
385 }
386
387ctype( type )TWORD type;{ /* map types which are not defined on the local machine */
388 switch( BTYPE(type) ){
389
390 case LONG:
391 MODTYPE(type,INT);
392 break;
393
394 case ULONG:
395 MODTYPE(type,UNSIGNED);
396 }
397 return( type );
398 }
399
400noinit() { /* curid is a variable which is defined but
401 is not initialized (and not a function );
402 This routine returns the stroage class for an uninitialized declaration */
403
404 return(EXTERN);
405
406 }
407
408commdec( id ){ /* make a common declaration for id, if reasonable */
409 register struct symtab *q;
410 OFFSZ off, tsize();
411
412 q = &stab[id];
413 printf( " .comm %s,", exname( q->sname ) );
414 off = tsize( q->stype, q->dimoff, q->sizoff );
895241c8 415 printf( "%d\n" /*CONFMT*/, off/SZCHAR );
b4204852
SL
416 }
417
7b1562c4
SL
418prtdcon(p)
419 register NODE *p;
420{
421 register int o = p->in.op;
422 int i;
423
424 if (o != DCON && o != FCON)
425 return;
426 /*
427 * Clobber constants of value zero so
428 * we can generate more efficient code.
429 */
430 if ((o == DCON && p->dpn.dval == 0) ||
431 (o == FCON && p->fpn.fval == 0)) {
432 p->in.op = ICON;
433 p->tn.rval = NONAME;
434 return;
435 }
436 locctr(DATA);
437 defalign(o == DCON ? ALDOUBLE : ALFLOAT);
438 deflab(i = getlab());
439 if (o == FCON)
440 fincode(p->fpn.fval, SZFLOAT);
441 else
442 fincode(p->dpn.dval, SZDOUBLE);
443 p->tn.lval = 0;
444 p->tn.rval = -i;
445 p->in.type = (o == DCON ? DOUBLE : FLOAT);
446 p->in.op = NAME;
447}
b4204852
SL
448
449isitfloat( s ) char *s; {
7b1562c4
SL
450 union cvt {
451 double d;
452 int n[2];
453 } cvt;
b4204852 454 double atof();
7b1562c4
SL
455
456 /* avoid floating point exception for double -> float conversions */
457 dcon = cvt.d = atof(s);
458 if( cvt.n[1] == 0 ){
459 fcon = dcon;
460 return( FCON );
461 }
462 return( DCON );
b4204852
SL
463 }
464
465ecode( p ) NODE *p; {
466
467 /* walk the tree and write out the nodes.. */
468
469 if( nerrors ) return;
470 p2tree( p );
471 p2compile( p );
472 }
473
474#ifndef ONEPASS
475tlen(p) NODE *p;
476{
477 switch(p->in.type) {
478 case CHAR:
479 case UCHAR:
480 return(1);
481
482 case SHORT:
483 case USHORT:
484 return(2);
485
486 case DOUBLE:
487 return(8);
488
489 default:
490 return(4);
491 }
492 }
493#endif