xref: /csrg-svn/old/pcc/ccom.vax/local.c (revision 32914)
1 #ifndef lint
2 static char *sccsid ="@(#)local.c	1.9 (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 cast( 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 
19 NODE *
20 clocal(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 
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 );
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;
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 			}
139 		else if( m != FLOAT && m != DOUBLE )
140 			break;
141 
142 		/* clobber conversion */
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;
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 		}
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 
188 andable( p ) NODE *p; {
189 	return(1);  /* all names can have & taken on them */
190 	}
191 
192 cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */
193 	autooff = AUTOINIT;
194 	}
195 
196 cisreg( 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 */
204 #ifdef SPRECC
205 		|| t==FLOAT
206 #endif
207 		|| ISPTR(t)) return (1);			/* wnj */
208 #endif
209 	return(0);
210 	}
211 
212 NODE *
213 offcon( 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 
231 static inwd	/* current bit offsed in word */;
232 static word	/* word being built from fields */;
233 
234 incode( 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 (nerrors) return;
243 	if((sz+inwd) > SZINT) cerror("incode: field > int");
244 	word |= ((unsigned)(p->tn.lval<<(32-sz))) >> (32-sz-inwd);
245 	inwd += sz;
246 	inoff += sz;
247 	if(inoff%SZINT == 0) {
248 		printf( "	.long	0x%x\n", word);
249 		word = inwd = 0;
250 		}
251 	}
252 
253 fincode( d, sz ) double d; {
254 	/* output code to initialize space of size sz to the value d */
255 	/* the proper alignment has been obtained */
256 	/* inoff is updated to have the proper final value */
257 	/* on the target machine, write it out in octal! */
258 
259 
260 	if (nerrors) return;
261 	printf("	%s	0%c%.20e\n", sz == SZDOUBLE ? ".double" : ".float",
262 		sz == SZDOUBLE ? 'd' : 'f', d);
263 	inoff += sz;
264 	}
265 
266 cinit( p, sz ) NODE *p; {
267 	NODE *l;
268 
269 	/*
270 	 * as a favor (?) to people who want to write
271 	 *     int i = 9600/134.5;
272 	 * we will, under the proper circumstances, do
273 	 * a coersion here.
274 	 */
275 	switch (p->in.type) {
276 	case INT:
277 	case UNSIGNED:
278 		l = p->in.left;
279 		if (l->in.op != SCONV ||
280 		    (l->in.left->tn.op != DCON && l->in.left->tn.op != FCON))
281 			break;
282 		l->in.op = FREE;
283 		l = l->in.left;
284 		l->tn.lval = l->tn.op == DCON ? (long)(l->dpn.dval) :
285 			(long)(l->fpn.fval);
286 		l->tn.rval = NONAME;
287 		l->tn.op = ICON;
288 		l->tn.type = INT;
289 		p->in.left = l;
290 		break;
291 	}
292 	/* arrange for the initialization of p into a space of size sz */
293 	/* the proper alignment has been opbtained */
294 	/* inoff is updated to have the proper final value */
295 	ecode( p );
296 	inoff += sz;
297 	}
298 
299 vfdzero( n ){ /* define n bits of zeros in a vfd */
300 
301 	if( n <= 0 ) return;
302 
303 	if (nerrors) return;
304 	inwd += n;
305 	inoff += n;
306 	if( inoff%ALINT ==0 ) {
307 		printf( "	.long	0x%x\n", word );
308 		word = inwd = 0;
309 		}
310 	}
311 
312 char *
313 exname( p ) char *p; {
314 	/* make a name look like an external name in the local machine */
315 
316 #ifndef FLEXNAMES
317 	static char text[NCHNAM+1];
318 #else
319 	static char text[BUFSIZ+1];
320 #endif
321 
322 	register i;
323 
324 	text[0] = '_';
325 #ifndef FLEXNAMES
326 	for( i=1; *p&&i<NCHNAM; ++i )
327 #else
328 	for( i=1; *p; ++i )
329 #endif
330 		text[i] = *p++;
331 
332 	text[i] = '\0';
333 #ifndef FLEXNAMES
334 	text[NCHNAM] = '\0';  /* truncate */
335 #endif
336 
337 	return( text );
338 	}
339 
340 ctype( type ) TWORD type;
341 	{ /* map types which are not defined on the local machine */
342 	switch( BTYPE(type) ){
343 
344 	case LONG:
345 		MODTYPE(type,INT);
346 		break;
347 
348 	case ULONG:
349 		MODTYPE(type,UNSIGNED);
350 		}
351 	return( type );
352 	}
353 
354 noinit() { /* curid is a variable which is defined but
355 	is not initialized (and not a function );
356 	This routine returns the stroage class for an uninitialized declaration */
357 
358 	return(EXTERN);
359 
360 	}
361 
362 commdec( id ){ /* make a common declaration for id, if reasonable */
363 	register struct symtab *q;
364 	OFFSZ off, tsize();
365 
366 	if (nerrors) return;
367 	q = &stab[id];
368 	printf( "	.comm	%s,", exname( q->sname ) );
369 	off = tsize( q->stype, q->dimoff, q->sizoff );
370 	printf( CONFMT, off/SZCHAR );
371 	printf( "\n" );
372 	}
373 
374 isitlong( cb, ce ){ /* is lastcon to be long or short */
375 	/* cb is the first character of the representation, ce the last */
376 
377 	if( ce == 'l' || ce == 'L' ||
378 		lastcon >= (1L << (SZINT-1) ) ) return (1);
379 	return(0);
380 	}
381 
382 
383 isitfloat( s ) char *s; {
384 	union cvt {
385 		double	d;
386 		int	n[2];
387 	} cvt;
388 	double atof();
389 
390 	/* avoid floating point exception for double -> float conversions */
391 	dcon = cvt.d = atof(s);
392 	if( cvt.n[1] == 0 ){
393 		fcon = dcon;
394 		return( FCON );
395 		}
396 	return( DCON );
397 	}
398 
399 ecode( p ) NODE *p; {
400 
401 	/* walk the tree and write out the nodes.. */
402 
403 	if( nerrors ) return;
404 	p2tree( p );
405 	p2compile( p );
406 	}
407 
408 #ifndef ONEPASS
409 tlen(p) NODE *p;
410 {
411 	switch(p->in.type) {
412 		case CHAR:
413 		case UCHAR:
414 			return(1);
415 
416 		case SHORT:
417 		case USHORT:
418 			return(2);
419 
420 		case DOUBLE:
421 			return(8);
422 
423 		default:
424 			return(4);
425 		}
426 	}
427 #endif
428