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