xref: /original-bsd/old/pcc/ccom.vax/local.c (revision 92c664ec)
1 #ifndef lint
2 static char *sccsid ="@(#)local.c	1.16 (Berkeley) 12/11/87";
3 #endif lint
4 
5 # include "pass1.h"
6 
7 /*	this file contains code which is dependent on the target machine */
8 
9 NODE *
10 clocal(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 = (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 
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 
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 
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:
87 		m = p->in.type;
88 		ml = p->in.left->in.type;
89 		if(m == ml)
90 			goto clobber;
91 		o = p->in.left->in.op;
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 );
107 			if( o == FCON )
108 				r->tn.lval = ml == INT ?
109 					(int) p->in.left->fpn.fval :
110 					(unsigned) p->in.left->fpn.fval;
111 			else
112 				r->tn.lval = ml == INT ?
113 					(int) p->in.left->dpn.dval :
114 					(unsigned) p->in.left->dpn.dval;
115 			r->tn.rval = NONAME;
116 			p->in.left->in.op = FREE;
117 			p->in.left = r;
118 			o = ICON;
119 			if( m == ml )
120 				goto clobber;
121 			}
122 		/* now, look for conversions downwards */
123 
124 		if( o == ICON ){ /* simulate the conversion here */
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 			}
149 		else
150 			break;
151 
152 	clobber:
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;
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 		}
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) )
188 						p->in.left->in.type = UNSIGNED;
189 					else
190 						p->in.left->in.type = INT;
191 				}
192 		break;
193 		}
194 
195 	return(p);
196 	}
197 
198 /*ARGSUSED*/
199 andable( p ) NODE *p; {
200 	return(1);  /* all names can have & taken on them */
201 	}
202 
203 cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */
204 	autooff = AUTOINIT;
205 	}
206 
207 cisreg( 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 */
215 #ifdef SPRECC
216 		|| t==FLOAT
217 #endif
218 		|| ISPTR(t)) return (1);			/* wnj */
219 #endif
220 	return(0);
221 	}
222 
223 /*ARGSUSED*/
224 NODE *
225 offcon( 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 */
234 	/* in general they  are necessary for offcon, but not on VAX */
235 
236 	p = bcon(0);
237 	p->tn.lval = off/SZCHAR;
238 	return(p);
239 
240 	}
241 
242 
243 static inwd	/* current bit offsed in word */;
244 static CONSZ word	/* word being built from fields */;
245 
246 incode( 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 
254 	if(nerrors) return;
255 	if((sz+inwd) > SZINT) cerror("incode: field > int");
256 	word |= ((unsigned)(p->tn.lval<<(32-sz))) >> (32-sz-inwd);
257 	inwd += sz;
258 	inoff += sz;
259 	if(inoff%SZINT == 0) {
260 		printf( "	.long	0x%lx\n", word);
261 		word = inwd = 0;
262 		}
263 	}
264 
265 fincode( 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 
272 	if (nerrors) return;
273 	printf("	%s	0%c%.20e\n", sz == SZDOUBLE ? ".double" : ".float",
274 		sz == SZDOUBLE ? 'd' : 'f', d);
275 	inoff += sz;
276 	}
277 
278 cinit( p, sz ) NODE *p; {
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
285 	 * a coercion here.
286 	 */
287 	switch (p->in.type) {
288 	case INT:
289 	case UNSIGNED:
290 		l = p->in.left;
291 		if (l->in.op != SCONV ||
292 		    (l->in.left->tn.op != DCON && l->in.left->tn.op != FCON))
293 			break;
294 		l->in.op = FREE;
295 		l = l->in.left;
296 		l->tn.lval = l->tn.op == DCON ? (long)(l->dpn.dval) :
297 			(long)(l->fpn.fval);
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 */
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 
311 vfdzero( n ){ /* define n bits of zeros in a vfd */
312 
313 	if( n <= 0 ) return;
314 
315 	if (nerrors) return;
316 	inwd += n;
317 	inoff += n;
318 	if( inoff%ALINT ==0 ) {
319 		printf( "	.long	0x%lx\n", word );
320 		word = inwd = 0;
321 		}
322 	}
323 
324 char *
325 exname( 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 
334 	register int i;
335 
336 	text[0] = '_';
337 #ifndef FLEXNAMES
338 	for( i=1; *p&&i<NCHNAM; ++i )
339 #else
340 	for( i=1; *p; ++i )
341 #endif
342 		text[i] = *p++;
343 
344 	text[i] = '\0';
345 #ifndef FLEXNAMES
346 	text[NCHNAM] = '\0';  /* truncate */
347 #endif
348 
349 	return( text );
350 	}
351 
352 ctype( type ) TWORD type;
353 	{ /* map types which are not defined on the local machine */
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 
366 noinit() { /* curid is a variable which is defined but
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 
374 commdec( id ){ /* make a common declaration for id, if reasonable */
375 	register struct symtab *q;
376 	OFFSZ off, tsize();
377 
378 	if (nerrors) return;
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 );
383 	putchar( '\n' );
384 	}
385 
386 prtdcon(p)
387 	register NODE *p;
388 {
389 	register int o = p->in.op;
390 	int i;
391 
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;
403 	}
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 }
416 
417 ecode( 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 	}
425 
426 #ifndef ONEPASS
427 tlen(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:
436 			return(SZSHORT/SZCHAR);
437 
438 		case DOUBLE:
439 			return(SZDOUBLE/SZCHAR);
440 
441 		default:
442 			return(SZINT/SZCHAR);
443 		}
444 	}
445 #endif
446