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