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