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