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