BSD 4_3_Reno release
[unix-history] / usr / src / libexec / pcc / ccom.vax / local.c
CommitLineData
4d89f1ac 1#ifndef lint
ca67e7b4 2static char *sccsid ="@(#)local.c 1.17 (Berkeley) 5/11/88";
4d89f1ac
RC
3#endif lint
4
13105c45 5# include "pass1.h"
fd18d838
ML
6
7/* this file contains code which is dependent on the target machine */
8
9NODE *
31bdb7a0 10clocal(p) register NODE *p; {
fd18d838
ML
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;
31bdb7a0
DS
26 register int o;
27 register int m, ml;
fd18d838
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 = (q->sclass==AUTO?STKREG:ARGREG);
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 break;
60
61 }
62 break;
63
31bdb7a0
DS
64 case LT:
65 case LE:
66 case GT:
67 case GE:
68 if( ISPTR( p->in.left->in.type ) || ISPTR( p->in.right->in.type ) ){
69 p->in.op += (ULT-LT);
70 }
71 break;
72
fd18d838
ML
73 case PCONV:
74 /* do pointer conversions for char and longs */
75 ml = p->in.left->in.type;
76 if( ( ml==CHAR || ml==UCHAR || ml==SHORT || ml==USHORT ) && p->in.left->in.op != ICON ) break;
77
78 /* pointers all have the same representation; the type is inherited */
79
fd18d838
ML
80 p->in.left->in.type = p->in.type;
81 p->in.left->fn.cdim = p->fn.cdim;
82 p->in.left->fn.csiz = p->fn.csiz;
83 p->in.op = FREE;
84 return( p->in.left );
85
86 case SCONV:
31bdb7a0
DS
87 m = p->in.type;
88 ml = p->in.left->in.type;
89 if(m == ml)
90 goto clobber;
4d89f1ac 91 o = p->in.left->in.op;
31bdb7a0
DS
92 if(m == FLOAT || m == DOUBLE) {
93 if(o==SCONV &&
94 ml == DOUBLE &&
95 p->in.left->in.left->in.type==m) {
96 p->in.op = p->in.left->in.op = FREE;
97 return(p->in.left->in.left);
98 }
99 /* see makety() for constant conversions */
100 break;
101 }
102 if(ml == FLOAT || ml == DOUBLE){
103 if(o != FCON && o != DCON)
104 break;
105 ml = ISUNSIGNED(m) ? UNSIGNED : INT; /* LONG? */
106 r = block( ICON, (NODE *)NULL, (NODE *)NULL, ml, 0, 0 );
4d89f1ac 107 if( o == FCON )
31bdb7a0
DS
108 r->tn.lval = ml == INT ?
109 (int) p->in.left->fpn.fval :
110 (unsigned) p->in.left->fpn.fval;
4d89f1ac 111 else
31bdb7a0
DS
112 r->tn.lval = ml == INT ?
113 (int) p->in.left->dpn.dval :
114 (unsigned) p->in.left->dpn.dval;
4d89f1ac
RC
115 r->tn.rval = NONAME;
116 p->in.left->in.op = FREE;
117 p->in.left = r;
31bdb7a0
DS
118 o = ICON;
119 if( m == ml )
120 goto clobber;
4d89f1ac 121 }
fd18d838
ML
122 /* now, look for conversions downwards */
123
31bdb7a0 124 if( o == ICON ){ /* simulate the conversion here */
fd18d838
ML
125 CONSZ val;
126 val = p->in.left->tn.lval;
127 switch( m ){
128 case CHAR:
129 p->in.left->tn.lval = (char) val;
130 break;
131 case UCHAR:
132 p->in.left->tn.lval = val & 0XFF;
133 break;
134 case USHORT:
135 p->in.left->tn.lval = val & 0XFFFFL;
136 break;
137 case SHORT:
138 p->in.left->tn.lval = (short)val;
139 break;
140 case UNSIGNED:
141 p->in.left->tn.lval = val & 0xFFFFFFFFL;
142 break;
143 case INT:
144 p->in.left->tn.lval = (int)val;
145 break;
146 }
147 p->in.left->in.type = m;
148 }
31bdb7a0 149 else
472582a4 150 break;
fd18d838 151
31bdb7a0 152 clobber:
fd18d838
ML
153 p->in.op = FREE;
154 return( p->in.left ); /* conversion gets clobbered */
155
156 case PVCONV:
157 case PMCONV:
158 if( p->in.right->in.op != ICON ) cerror( "bad conversion", 0);
159 p->in.op = FREE;
160 return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) );
161
162 case RS:
163 case ASG RS:
164 /* convert >> to << with negative shift count */
165 /* only if type of left operand is not unsigned */
166
167 if( ISUNSIGNED(p->in.left->in.type) ) break;
4d89f1ac
RC
168 if( p->in.right->in.op != UNARY MINUS )
169 p->in.right = buildtree( UNARY MINUS, p->in.right, NIL );
170 else {
171 r = p->in.right;
172 p->in.right = p->in.right->in.left;
173 r->in.op = FREE;
174 }
fd18d838
ML
175 if( p->in.op == RS ) p->in.op = LS;
176 else p->in.op = ASG LS;
177 break;
178
179 case FLD:
180 /* make sure that the second pass does not make the
181 descendant of a FLD operator into a doubly indexed OREG */
182
183 if( p->in.left->in.op == UNARY MUL
184 && (r=p->in.left->in.left)->in.op == PCONV)
185 if( r->in.left->in.op == PLUS || r->in.left->in.op == MINUS )
186 if( ISPTR(r->in.type) ) {
187 if( ISUNSIGNED(p->in.left->in.type) )
c30a740a 188 p->in.left->in.type = UCHAR;
fd18d838 189 else
c30a740a 190 p->in.left->in.type = CHAR;
fd18d838
ML
191 }
192 break;
193 }
194
195 return(p);
196 }
197
dd27ff22 198/*ARGSUSED*/
fd18d838
ML
199andable( p ) NODE *p; {
200 return(1); /* all names can have & taken on them */
201 }
202
203cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */
204 autooff = AUTOINIT;
205 }
206
207cisreg( t ) TWORD t; { /* is an automatic variable of type t OK for a register variable */
208
209#ifdef TRUST_REG_CHAR_AND_REG_SHORT
210 if( t==INT || t==UNSIGNED || t==LONG || t==ULONG /* tbl */
211 || t==CHAR || t==UCHAR || t==SHORT /* tbl */
212 || t==USHORT || ISPTR(t)) return(1); /* tbl */
213#else
214 if( t==INT || t==UNSIGNED || t==LONG || t==ULONG /* wnj */
4d89f1ac
RC
215#ifdef SPRECC
216 || t==FLOAT
217#endif
fd18d838
ML
218 || ISPTR(t)) return (1); /* wnj */
219#endif
220 return(0);
221 }
222
dd27ff22 223/*ARGSUSED*/
fd18d838
ML
224NODE *
225offcon( off, t, d, s ) OFFSZ off; TWORD t; {
226
227 /* return a node, for structure references, which is suitable for
228 being added to a pointer of type t, in order to be off bits offset
229 into a structure */
230
231 register NODE *p;
232
233 /* t, d, and s are the type, dimension offset, and sizeoffset */
dd27ff22 234 /* in general they are necessary for offcon, but not on VAX */
fd18d838
ML
235
236 p = bcon(0);
237 p->tn.lval = off/SZCHAR;
238 return(p);
239
240 }
241
242
243static inwd /* current bit offsed in word */;
31bdb7a0 244static CONSZ word /* word being built from fields */;
fd18d838
ML
245
246incode( p, sz ) register NODE *p; {
247
248 /* generate initialization code for assigning a constant c
249 to a field of width sz */
250 /* we assume that the proper alignment has been obtained */
251 /* inoff is updated to have the proper final value */
252 /* we also assume sz < SZINT */
253
c30a740a 254 inoff += sz;
31bdb7a0 255 if(nerrors) return;
fd18d838
ML
256 if((sz+inwd) > SZINT) cerror("incode: field > int");
257 word |= ((unsigned)(p->tn.lval<<(32-sz))) >> (32-sz-inwd);
258 inwd += sz;
fd18d838 259 if(inoff%SZINT == 0) {
31bdb7a0 260 printf( " .long 0x%lx\n", word);
fd18d838
ML
261 word = inwd = 0;
262 }
263 }
264
265fincode( d, sz ) double d; {
266 /* output code to initialize space of size sz to the value d */
267 /* the proper alignment has been obtained */
268 /* inoff is updated to have the proper final value */
269 /* on the target machine, write it out in octal! */
270
271
c30a740a 272 if(!nerrors)
fd18d838
ML
273 printf(" %s 0%c%.20e\n", sz == SZDOUBLE ? ".double" : ".float",
274 sz == SZDOUBLE ? 'd' : 'f', d);
275 inoff += sz;
276 }
277
278cinit( p, sz ) NODE *p; {
03f4d7a6
KM
279 NODE *l;
280
281 /*
282 * as a favor (?) to people who want to write
283 * int i = 9600/134.5;
284 * we will, under the proper circumstances, do
31bdb7a0 285 * a coercion here.
03f4d7a6
KM
286 */
287 switch (p->in.type) {
288 case INT:
289 case UNSIGNED:
290 l = p->in.left;
13105c45
RC
291 if (l->in.op != SCONV ||
292 (l->in.left->tn.op != DCON && l->in.left->tn.op != FCON))
293 break;
03f4d7a6
KM
294 l->in.op = FREE;
295 l = l->in.left;
13105c45
RC
296 l->tn.lval = l->tn.op == DCON ? (long)(l->dpn.dval) :
297 (long)(l->fpn.fval);
03f4d7a6
KM
298 l->tn.rval = NONAME;
299 l->tn.op = ICON;
300 l->tn.type = INT;
301 p->in.left = l;
302 break;
303 }
304 /* arrange for the initialization of p into a space of size sz */
fd18d838
ML
305 /* the proper alignment has been opbtained */
306 /* inoff is updated to have the proper final value */
307 ecode( p );
308 inoff += sz;
309 }
310
311vfdzero( n ){ /* define n bits of zeros in a vfd */
312
313 if( n <= 0 ) return;
314
c30a740a 315 inoff += n;
e324b298 316 if (nerrors) return;
fd18d838 317 inwd += n;
fd18d838 318 if( inoff%ALINT ==0 ) {
31bdb7a0 319 printf( " .long 0x%lx\n", word );
fd18d838
ML
320 word = inwd = 0;
321 }
322 }
323
324char *
325exname( p ) char *p; {
326 /* make a name look like an external name in the local machine */
327
328#ifndef FLEXNAMES
329 static char text[NCHNAM+1];
330#else
331 static char text[BUFSIZ+1];
332#endif
333
31bdb7a0 334 register int i;
fd18d838
ML
335
336 text[0] = '_';
337#ifndef FLEXNAMES
88bb0c9f 338 for( i=1; *p&&i<NCHNAM; ++i )
fd18d838 339#else
88bb0c9f 340 for( i=1; *p; ++i )
fd18d838
ML
341#endif
342 text[i] = *p++;
fd18d838
ML
343
344 text[i] = '\0';
345#ifndef FLEXNAMES
346 text[NCHNAM] = '\0'; /* truncate */
347#endif
348
349 return( text );
350 }
351
4d89f1ac
RC
352ctype( type ) TWORD type;
353 { /* map types which are not defined on the local machine */
fd18d838
ML
354 switch( BTYPE(type) ){
355
356 case LONG:
357 MODTYPE(type,INT);
358 break;
359
360 case ULONG:
361 MODTYPE(type,UNSIGNED);
362 }
363 return( type );
364 }
365
4d89f1ac 366noinit() { /* curid is a variable which is defined but
fd18d838
ML
367 is not initialized (and not a function );
368 This routine returns the stroage class for an uninitialized declaration */
369
370 return(EXTERN);
371
372 }
373
374commdec( id ){ /* make a common declaration for id, if reasonable */
375 register struct symtab *q;
376 OFFSZ off, tsize();
377
e324b298 378 if (nerrors) return;
fd18d838
ML
379 q = &stab[id];
380 printf( " .comm %s,", exname( q->sname ) );
381 off = tsize( q->stype, q->dimoff, q->sizoff );
382 printf( CONFMT, off/SZCHAR );
31bdb7a0 383 putchar( '\n' );
fd18d838
ML
384 }
385
31bdb7a0
DS
386prtdcon(p)
387 register NODE *p;
388{
389 register int o = p->in.op;
390 int i;
fd18d838 391
31bdb7a0
DS
392 if (o != DCON && o != FCON)
393 return;
394 /*
395 * Clobber constants of value zero so
396 * we can generate more efficient code.
397 */
398 if ((o == DCON && p->dpn.dval == 0) ||
399 (o == FCON && p->fpn.fval == 0)) {
400 p->in.op = ICON;
401 p->tn.rval = NONAME;
402 return;
fd18d838 403 }
31bdb7a0
DS
404 locctr(DATA);
405 defalign(o == DCON ? ALDOUBLE : ALFLOAT);
406 deflab(i = getlab());
407 if (o == FCON)
408 fincode(p->fpn.fval, SZFLOAT);
409 else
410 fincode(p->dpn.dval, SZDOUBLE);
411 p->tn.lval = 0;
412 p->tn.rval = -i;
413 p->in.type = (o == DCON ? DOUBLE : FLOAT);
414 p->in.op = NAME;
415}
fd18d838 416
fd18d838
ML
417ecode( p ) NODE *p; {
418
419 /* walk the tree and write out the nodes.. */
420
421 if( nerrors ) return;
422 p2tree( p );
423 p2compile( p );
424 }
fd18d838
ML
425
426#ifndef ONEPASS
427tlen(p) NODE *p;
428{
429 switch(p->in.type) {
430 case CHAR:
431 case UCHAR:
432 return(1);
433
434 case SHORT:
435 case USHORT:
1504b363 436 return(SZSHORT/SZCHAR);
fd18d838
ML
437
438 case DOUBLE:
1504b363 439 return(SZDOUBLE/SZCHAR);
fd18d838
ML
440
441 default:
1504b363 442 return(SZINT/SZCHAR);
fd18d838
ML
443 }
444 }
445#endif