xref: /netbsd/external/bsd/pcc/dist/pcc/arch/vax/local.c (revision 6935091c)
1 /*	Id: local.c,v 1.31 2015/11/13 11:38:47 ragge Exp 	*/
2 /*	$NetBSD: local.c,v 1.1.1.6 2016/02/09 20:28:35 plunky Exp $	*/
3 /*
4  * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * Redistributions of source code and documentation must retain the above
11  * copyright notice, this list of conditions and the following disclaimer.
12  * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditionsand the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  * All advertising materials mentioning features or use of this software
16  * must display the following acknowledgement:
17  *	This product includes software developed or owned by Caldera
18  *	International, Inc.
19  * Neither the name of Caldera International, Inc. nor the names of other
20  * contributors may be used to endorse or promote products derived from
21  * this software without specific prior written permission.
22  *
23  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
24  * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27  * DISCLAIMED.	IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
28  * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
32  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
33  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 # include "pass1.h"
38 
39 #ifndef LANG_CXX
40 #define NODE P1ND
41 #undef NIL
42 #define	NIL NULL
43 #define	nfree p1nfree
44 #define	fwalk p1fwalk
45 #endif
46 
47 static void r1arg(NODE *p, NODE *q);
48 
49 
50 /*	this file contains code which is dependent on the target machine */
51 
52 NODE *
clocal(p)53 clocal(p) NODE *p; {
54 
55 	/* this is called to do local transformations on
56 	   an expression tree preparitory to its being
57 	   written out in intermediate code.
58 	*/
59 
60 	/* the major essential job is rewriting the
61 	   automatic variables and arguments in terms of
62 	   REG and OREG nodes */
63 	/* conversion ops which are not necessary are also clobbered here */
64 	/* in addition, any special features (such as rewriting
65 	   exclusive or) are easily handled here as well */
66 
67 	register struct symtab *q;
68 	register NODE *r, *l;
69 	register int o;
70 	register int ml;
71 
72 
73 #ifdef PCC_DEBUG
74 	if (xdebug) {
75 		printf("clocal(%p)\n", p);
76 		if (xdebug>1)
77 			fwalk(p, eprint, 0);
78 	}
79 #endif
80 
81 	switch( o = p->n_op ){
82 
83 	case NAME:
84 		if((q = p->n_sp) == 0 ) { /* already processed; ignore... */
85 			return(p);
86 			}
87 		switch( q->sclass ){
88 
89 		case REGISTER:
90 		case AUTO:
91 		case PARAM:
92 			/* fake up a structure reference */
93 			r = block( REG, NIL, NIL, PTR+STRTY, 0, 0 );
94 			r->n_lval = 0;
95 			r->n_rval = (q->sclass==PARAM?ARGREG:FPREG);
96 			p = stref( block( STREF, r, p, 0, 0, 0 ) );
97 			break;
98 		}
99 		break;
100 
101 	case FORCE:
102 		p->n_op = ASSIGN;
103 		p->n_right = p->n_left;
104 		p->n_left = block(REG, NIL, NIL, p->n_type, 0, 0);
105 		p->n_left->n_rval = p->n_left->n_type == BOOL ?
106 		    RETREG(CHAR) : RETREG(p->n_type);
107 		break;
108 
109 	case SCONV:
110 		l = p->n_left;
111 		ml = p->n_type;
112 #if 0
113 		if (ml == INT && l->n_type == UNSIGNED) {
114 			p = nfree(p);
115 			break;
116 		}
117 #endif
118 		if (l->n_op == ICON) {
119 			if (l->n_sp == 0) {
120 				p->n_type = UNSIGNED;
121 				concast(l, p->n_type);
122 			} else if (ml != INT && ml != UNSIGNED)
123 				break;
124 			l->n_type = ml;
125 			l->n_ap = 0;
126 			p = nfree(p);
127 			break;
128 		}
129 		break;
130 
131 	case STCALL:
132 		/* see if we have been here before */
133 		for (r = p->n_right; r->n_op == CM; r = r->n_left)
134 			;
135 		if (r->n_op == ASSIGN)
136 			break;
137 
138 		/* FALLTHROUGH */
139 	case USTCALL:
140 		/* Allocate buffer on stack to bounce via */
141 		/* create fake symtab here */
142 		q = getsymtab("77fake", STEMP);
143 		q->stype = BTYPE(p->n_type);
144 		q->sdf = p->n_df;
145 		q->sap = p->n_ap;
146 		q->soffset = NOOFFSET;
147 		q->sclass = AUTO;
148 		oalloc(q, &autooff);
149 		r1arg(p, buildtree(ADDROF, nametree(q), 0));
150 		break;
151 	}
152 #ifdef PCC_DEBUG
153 	if (xdebug) {
154 		printf("clocal end(%p)\n", p);
155 		if (xdebug>1)
156 			fwalk(p, eprint, 0);
157 	}
158 #endif
159 
160 	return(p);
161 }
162 
163 /*
164  * Add R1 with the dest address as arg to a struct return call.
165  */
166 static void
r1arg(NODE * p,NODE * q)167 r1arg(NODE *p, NODE *q)
168 {
169 	NODE *r;
170 
171 	r = block(REG, NIL, NIL, PTR|VOID, 0, 0);
172 	regno(r) = R1;
173 	r = buildtree(ASSIGN, r, q);
174 	if (p->n_op == USTCALL) {
175 		p->n_op = STCALL;
176 		p->n_right = r;
177 	} else if (p->n_right->n_op != CM) {
178 		p->n_right = block(CM, r, p->n_right, INT, 0, 0);
179 	} else {
180 		for (q = p->n_right; q->n_left->n_op == CM; q = q->n_left)
181 			;
182 		q->n_left = block(CM, r, q->n_left, INT, 0, 0);
183 	}
184 }
185 
186 void
myp2tree(NODE * p)187 myp2tree(NODE *p)
188 {
189 	struct symtab *sp;
190 
191 	if ((cdope(p->n_op) & CALLFLG) && p->n_left->n_op == ADDROF &&
192 	    p->n_left->n_left->n_op == NAME) {
193 		NODE *q = p->n_left->n_left;
194 		nfree(p->n_left);
195 		p->n_left = q;
196 		q->n_op = ICON;
197 	}
198 
199 	if (p->n_op != FCON)
200 		return;
201 
202 	sp = tmpalloc(sizeof(struct symtab));
203 	sp->sclass = STATIC;
204 	sp->sap = 0;
205 	sp->slevel = 1; /* fake numeric label */
206 	sp->soffset = getlab();
207 	sp->sflags = 0;
208 	sp->stype = p->n_type;
209 	sp->squal = (CON >> TSHIFT);
210 
211 	defloc(sp);
212 	inval(0, tsize(sp->stype, sp->sdf, sp->sap), p);
213 
214 	p->n_op = NAME;
215 	p->n_lval = 0;
216 	p->n_sp = sp;
217 
218 }
219 
220 /*
221  * Can we take & of a NAME?
222  */
223 int
andable(NODE * p)224 andable(NODE *p)
225 {
226 	/* for now, delay name reference to table, for PIC code generation */
227 	/* functions are called by name, convert they in myp2tree */
228 	return 0;
229 }
230 
231 /* is an automatic variable of type t OK for a register variable */
232 int
cisreg(TWORD t)233 cisreg(TWORD t)
234 {
235 	return(1);	/* all are now */
236 }
237 
238 /*
239  * Allocate off bits on the stack.  p is a tree that when evaluated
240  * is the multiply count for off, t is a storeable node where to write
241  * the allocated address.
242  */
243 void
spalloc(NODE * t,NODE * p,OFFSZ off)244 spalloc(NODE *t, NODE *p, OFFSZ off)
245 {
246 	NODE *sp;
247 
248 	p = buildtree(MUL, p, bcon(off/SZCHAR)); /* XXX word alignment? */
249 
250 	/* sub the size from sp */
251 	sp = block(REG, NIL, NIL, p->n_type, 0, 0);
252 	sp->n_lval = 0;
253 	sp->n_rval = STKREG;
254 	ecomp(buildtree(MINUSEQ, sp, p));
255 
256 	/* save the address of sp */
257 	sp = block(REG, NIL, NIL, PTR+INT, t->n_df, t->n_ap);
258 	sp->n_lval = 0;
259 	sp->n_rval = STKREG;
260 	t->n_type = sp->n_type;
261 	ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */
262 
263 }
264 
265 char *
exname(p)266 exname( p ) char *p; {
267 	/* make a name look like an external name in the local machine */
268 	/* vad is elf now */
269 	if (p == NULL)
270 		return "";
271 	return( p );
272 	}
273 
274 /* map types which are not defined on the local machine */
275 TWORD
ctype(TWORD type)276 ctype(TWORD type) {
277 	switch( BTYPE(type) ){
278 
279 	case LONG:
280 		MODTYPE(type,INT);
281 		break;
282 
283 	case ULONG:
284 		MODTYPE(type,UNSIGNED);
285 		break;
286 
287 	case LDOUBLE:	/* for now */
288 		MODTYPE(type,DOUBLE);
289 		}
290 	return( type );
291 	}
292 
293 void
calldec(NODE * p,NODE * q)294 calldec(NODE *p, NODE *q)
295 {
296 }
297 
298 void
extdec(struct symtab * q)299 extdec(struct symtab *q)
300 {
301 }
302 
303 /* make a common declaration for id, if reasonable */
304 void
defzero(struct symtab * sp)305 defzero(struct symtab *sp)
306 {
307 	int off, al;
308 	char *name;
309 
310 	name = getexname(sp);
311 	off = tsize(sp->stype, sp->sdf, sp->sap);
312 	SETOFF(off,SZCHAR);
313 	off /= SZCHAR;
314 	al = talign(sp->stype, sp->sap)/SZCHAR;
315 
316 	if (sp->sclass == STATIC) {
317 		if (sp->slevel == 0)
318 			printf("\t.local %s\n", name);
319 		else
320 			printf("\t.local " LABFMT "\n", sp->soffset);
321 	}
322 	if (sp->slevel == 0) {
323 		printf("\t.comm %s,0%o,%d\n", name, off, al);
324 	} else
325 		printf("\t.comm " LABFMT ",0%o,%d\n", sp->soffset, off, al);
326 }
327 
328 /*
329  * print out a constant node, may be associated with a label.
330  * Do not free the node after use.
331  * off is bit offset from the beginning of the aggregate
332  * fsz is the number of bits this is referring to
333  * XXX - floating point constants may be wrong if cross-compiling.
334  */
335 int
ninval(CONSZ off,int fsz,NODE * p)336 ninval(CONSZ off, int fsz, NODE *p)
337 {
338 	union { float f; double d; long double l; int i[3]; } u;
339 
340 	switch (p->n_type) {
341 	case LDOUBLE:
342 		u.i[2] = 0;
343 		u.l = (long double)((union flt *)p->n_dcon)->fp;
344 		printf("\t.long\t0x%x,0x%x,0x%x\n", u.i[0], u.i[1], u.i[2]);
345 		break;
346 	case DOUBLE:
347 		u.d = (double)((union flt *)p->n_dcon)->fp;
348 		printf("\t.long\t0x%x,0x%x\n", u.i[0], u.i[1]);
349 		break;
350 	case FLOAT:
351 		u.f = (float)((union flt *)p->n_dcon)->fp;
352 		printf("\t.long\t0x%x\n", u.i[0]);
353 		break;
354 	default:
355 		return 0;
356 	}
357 	return 1;
358 
359 }
360 /*
361  * Give target the opportunity of handling pragmas.
362  */
363 int
mypragma(char * str)364 mypragma(char *str)
365 {
366 	return 0;
367 }
368 
369 /*
370  * Called when a identifier has been declared, to give target last word.
371  */
372 void
fixdef(struct symtab * sp)373 fixdef(struct symtab *sp)
374 {
375 }
376 
377 void
pass1_lastchance(struct interpass * ip)378 pass1_lastchance(struct interpass *ip)
379 {
380 }
381