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