Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20160305155614

Diff

Diff from 1.38 to:

Annotations

Annotate by Age | Author | Mixed | None
/fisheye/browse/pcc/pcc/arch/mips/local.c

Annotated File View

ragge
1.38
1 /*      $Id: local.c,v 1.38 2016/03/05 15:56:14 ragge Exp $     */
ragge
1.1
2 /*
3  * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
4  * 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  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 /*
28  * MIPS port by Jan Enoksson (janeno-1@student.ltu.se) and
29  * Simon Olsson (simols-1@student.ltu.se) 2005.
30  */
31
gmcgarry
1.3
32 #include "pass1.h"
ragge
1.1
33
ragge
1.34
34 #ifndef LANG_CXX
35 #define NODE P1ND
36 #define ccopy p1tcopy
ragge
1.36
37 #define tcopy p1tcopy
ragge
1.34
38 #define tfree p1tfree
39 #define nfree p1nfree
40 #define fwalk p1fwalk
41 #define talloc p1alloc
42 #endif
43
gmcgarry
1.15
44 #define IALLOC(sz) (isinlining ? permalloc(sz) : tmpalloc(sz))
45
gmcgarry
1.3
46 /* this is called to do local transformations on
47  * an expression tree preparitory to its being
48  * written out in intermediate code.
49  */
ragge
1.1
50 NODE *
51 clocal(NODE *p)
52 {
gmcgarry
1.3
53         struct symtab *q;
54         NODE *r, *l;
55         int o;
gmcgarry
1.7
56         int m;
gmcgarry
1.6
57         TWORD ty;
gmcgarry
1.8
58         int tmpnrisptrvoid = 0;
ragge
1.1
59
gmcgarry
1.7
60 #ifdef PCC_DEBUG
61         if (xdebug) {
gmcgarry
1.8
62                 printf("clocal in: %p\n"p);
gmcgarry
1.7
63                 fwalk(peprint0);
64         }
65 #endif
gmcgarry
1.3
66
gmcgarry
1.6
67         switch (o = p->n_op) {
ragge
1.1
68
gmcgarry
1.8
69         case UCALL:
70         case CALL:
71         case STCALL:
72         case USTCALL:
73                 if (p->n_type == VOID)
74                         break;
75                 /*
76                  * if the function returns void*, ecode() invokes
77                  * delvoid() to convert it to uchar*.
78                  * We just let this happen on the ASSIGN to the temp,
79                  * and cast the pointer back to void* on access
80                  * from the temp.
81                  */
82                 if (p->n_type == PTR+VOID)
83                         isptrvoid = 1;
ragge
1.22
84                 r = tempnode(0p->n_typep->n_dfp->n_ap);
ragge
1.12
85                 tmpnr = regno(r);
ragge
1.22
86                 r = block(ASSIGNrpp->n_typep->n_dfp->n_ap);
gmcgarry
1.9
87
ragge
1.22
88                 p = tempnode(tmpnrr->n_typer->n_dfr->n_ap);
gmcgarry
1.8
89                 if (isptrvoid) {
ragge
1.25
90                         p = block(PCONVpNILPTR+VOIDp->n_df0);
gmcgarry
1.8
91                 }
gmcgarry
1.9
92                 p = buildtree(COMOPrp);
gmcgarry
1.8
93                 break;
94
ragge
1.1
95         case NAME:
96                 if ((q = p->n_sp) == NULL)
97                         return p/* Nothing to care about */
98
99                 switch (q->sclass) {
100
101                 case PARAM:
102                 case AUTO:
103                         /* fake up a structure reference */
104                         r = block(REGNILNILPTR+STRTY00);
ragge
1.36
105                         slval(r0);
gmcgarry
1.3
106                         r->n_rval = FP;
ragge
1.1
107                         p = stref(block(STREFrp000));
108                         break;
109
110                 case STATIC:
111                         if (q->slevel == 0)
112                                 break;
ragge
1.36
113                         slval(p0);
ragge
1.1
114                         p->n_sp = q;
115                         break;
116
117                 case REGISTER:
118                         p->n_op = REG;
ragge
1.36
119                         slval(p0);
ragge
1.1
120                         p->n_rval = q->soffset;
121                         break;
122
gmcgarry
1.7
123                 }
ragge
1.1
124                 break;
125
126         case FUNARG:
127                 /* Args smaller than int are given as int */
128                 if (p->n_type != CHAR && p->n_type != UCHAR && 
129                     p->n_type != SHORT && p->n_type != USHORT)
130                         break;
ragge
1.25
131                 p->n_left = block(SCONVp->n_leftNILINT00);
ragge
1.1
132                 p->n_type = INT;
ragge
1.25
133                 p->n_ap = 0;
ragge
1.1
134                 p->n_rval = SZINT;
135                 break;
136
137         case CBRANCH:
138                 l = p->n_left;
139
140                 /*
ragge
1.16
141                  * Remove unnecessary conversion ops.
ragge
1.1
142                  */
143                 if (clogop(l->n_op) && l->n_left->n_op == SCONV) {
144                         if (coptype(l->n_op) != BITYPE)
145                                 break;
146                         if (l->n_right->n_op == ICON) {
147                                 r = l->n_left->n_left;
148                                 if (r->n_type >= FLOAT && r->n_type <= LDOUBLE)
149                                         break;
150                                 /* Type must be correct */
gmcgarry
1.6
151                                 ty = r->n_type;
ragge
1.1
152                                 nfree(l->n_left);
153                                 l->n_left = r;
gmcgarry
1.6
154                                 l->n_type = ty;
155                                 l->n_right->n_type = ty;
ragge
1.1
156                         }
157 #if 0
158                           else if (l->n_right->n_op == SCONV &&
159                             l->n_left->n_type == l->n_right->n_type) {
160                                 r = l->n_left->n_left;
161                                 nfree(l->n_left);
162                                 l->n_left = r;
163                                 r = l->n_right->n_left;
164                                 nfree(l->n_right);
165                                 l->n_right = r;
166                         }
167 #endif
168                 }
169                 break;
170
171         case PCONV:
gmcgarry
1.7
172                 /* Remove redundant PCONV's. Be careful */
ragge
1.1
173                 l = p->n_left;
gmcgarry
1.7
174                 if (l->n_op == ICON) {
ragge
1.36
175                         slval(l, (unsigned)glval(l));
gmcgarry
1.7
176                         goto delp;
177                 }
gmcgarry
1.8
178                 if (l->n_type < INT || DEUNSIGN(l->n_type) == LONGLONG) {
gmcgarry
1.7
179                         /* float etc? */
ragge
1.25
180                         p->n_left = block(SCONVlNILUNSIGNED00);
gmcgarry
1.7
181                         break;
182                 }
183                 /* if left is SCONV, cannot remove */
184                 if (l->n_op == SCONV)
185                         break;
186
187                 /* avoid ADDROF TEMP */
188                 if (l->n_op == ADDROF && l->n_left->n_op == TEMP)
ragge
1.1
189                         break;
gmcgarry
1.7
190
191                 /* if conversion to another pointer type, just remove */
192                 if (p->n_type > BTMASK && l->n_type > BTMASK)
193                         goto delp;
194                 break;
195
196         delp:   l->n_type = p->n_type;
ragge
1.1
197                 l->n_qual = p->n_qual;
198                 l->n_df = p->n_df;
ragge
1.22
199                 l->n_ap = p->n_ap;
ragge
1.1
200                 nfree(p);
201                 p = l;
202                 break;
203
204         case SCONV:
205                 l = p->n_left;
206
207                 if (p->n_type == l->n_type) {
208                         nfree(p);
gmcgarry
1.8
209                         p = l;
210                         break;
ragge
1.1
211                 }
212
213                 if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 &&
ragge
1.31
214                     tsize(p->n_typep->n_dfp->n_ap) ==
215                     tsize(l->n_typel->n_dfl->n_ap)) {
ragge
1.1
216                         if (p->n_type != FLOAT && p->n_type != DOUBLE &&
217                             l->n_type != FLOAT && l->n_type != DOUBLE &&
218                             l->n_type != LDOUBLE && p->n_type != LDOUBLE) {
gmcgarry
1.8
219                                 if (l->n_op == NAME || l->n_op == UMUL ||
220                                     l->n_op == TEMP) {
ragge
1.1
221                                         l->n_type = p->n_type;
222                                         nfree(p);
gmcgarry
1.8
223                                         p = l;
224                                         break;
ragge
1.1
225                                 }
226                         }
227                 }
228
gmcgarry
1.8
229                 if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT &&
230                     coptype(l->n_op) == BITYPE) {
231                         l->n_type = p->n_type;
232                         nfree(p);
233                         p = l;
234                 }
235
236                 if (DEUNSIGN(p->n_type) == SHORT &&
237                     DEUNSIGN(l->n_type) == SHORT) {
ragge
1.1
238                         nfree(p);
gmcgarry
1.8
239                         p = l;
ragge
1.1
240                 }
241
gmcgarry
1.9
242                 /* convert float/double to int before to (u)char/(u)short */
gmcgarry
1.8
243                 if ((DEUNSIGN(p->n_type) == CHAR ||
244                     DEUNSIGN(p->n_type) == SHORT) &&
245                     (l->n_type == FLOAT || l->n_type == DOUBLE ||
246                     l->n_type == LDOUBLE)) {
ragge
1.22
247                         p = block(SCONVpNILp->n_typep->n_dfp->n_ap);
gmcgarry
1.8
248                         p->n_left->n_type = INT;
249                         break;
250                 }
251
gmcgarry
1.9
252                 /* convert (u)char/(u)short to int before float/double */
253                 if  ((p->n_type == FLOAT || p->n_type == DOUBLE ||
254                     p->n_type == LDOUBLE) && (DEUNSIGN(l->n_type) == CHAR ||
255                     DEUNSIGN(l->n_type) == SHORT)) {
ragge
1.22
256                         p = block(SCONVpNILp->n_typep->n_dfp->n_ap);
gmcgarry
1.9
257                         p->n_left->n_type = INT;
258                         break;
259                 }
gmcgarry
1.8
260
ragge
1.1
261                 o = l->n_op;
262                 m = p->n_type;
263
264                 if (o == ICON) {
ragge
1.36
265                         CONSZ val = glval(l);
ragge
1.1
266
267                         if (!ISPTR(m)) /* Pointers don't need to be conv'd */
268                             switch (m) {
gmcgarry
1.10
269                         case BOOL:
ragge
1.36
270                                 val = nncon(l) ? (val != 0) : 1;
271                                 slval(lval);
272                                 l->n_sp = NULL;
gmcgarry
1.10
273                                 break;
ragge
1.1
274                         case CHAR:
ragge
1.36
275                                 slval(l, (char)val);
ragge
1.1
276                                 break;
277                         case UCHAR:
ragge
1.36
278                                 slval(lval & 0377);
ragge
1.1
279                                 break;
280                         case SHORT:
ragge
1.36
281                                 slval(l, (short)val);
ragge
1.1
282                                 break;
283                         case USHORT:
ragge
1.36
284                                 slval(lval & 0177777);
ragge
1.1
285                                 break;
286                         case ULONG:
287                         case UNSIGNED:
ragge
1.36
288                                 slval(lval & 0xffffffff);
ragge
1.1
289                                 break;
290                         case LONG:
291                         case INT:
ragge
1.36
292                                 slval(l, (int)val);
ragge
1.1
293                                 break;
294                         case LONGLONG:
ragge
1.36
295                                 slval(l, (long long)val);
ragge
1.1
296                                 break;
297                         case ULONGLONG:
ragge
1.36
298                                 slval(lval);
ragge
1.1
299                                 break;
300                         case VOID:
301                                 break;
302                         case LDOUBLE:
303                         case DOUBLE:
304                         case FLOAT:
305                                 l->n_op = FCON;
ragge
1.38
306                                 l->n_dcon = fltallo();
307                                 FCAST(l->n_dcon)->fp = val;
ragge
1.1
308                                 break;
309                         default:
310                                 cerror("unknown type %d"m);
311                         }
312                         l->n_type = m;
313                         nfree(p);
314                         p = l;
gmcgarry
1.15
315                 } else if (o == FCON) {
ragge
1.36
316                         CONSZ lv;
317                         if (p->n_type == BOOL)
ragge
1.38
318                                 lv = !FLOAT_ISZERO(FCAST(l->n_dcon));
ragge
1.36
319                         else {
ragge
1.38
320                                 FLOAT_FP2INT(lvFCAST(l->n_dcon), m);
ragge
1.36
321                         }
322                         slval(llv);
gmcgarry
1.15
323                         l->n_sp = NULL;
324                         l->n_op = ICON;
325                         l->n_type = m;
ragge
1.25
326                         l->n_ap = 0;
gmcgarry
1.15
327                         nfree(p);
328                         p = clocal(l);
ragge
1.1
329                 }
330                 break;
331
332         case MOD:
333         case DIV:
334                 if (o == DIV && p->n_type != CHAR && p->n_type != SHORT)
335                         break;
336                 if (o == MOD && p->n_type != CHAR && p->n_type != SHORT)
337                         break;
338                 /* make it an int division by inserting conversions */
ragge
1.25
339                 p->n_left = block(SCONVp->n_leftNILINT00);
340                 p->n_right = block(SCONVp->n_rightNILINT00);
341                 p = block(SCONVpNILp->n_type00);
ragge
1.1
342                 p->n_left->n_type = INT;
343                 break;
344
345         case FORCE:
346                 /* put return value in return reg */
347                 p->n_op = ASSIGN;
348                 p->n_right = p->n_left;
ragge
1.25
349                 p->n_left = block(REGNILNILp->n_type00);
gmcgarry
1.3
350                 p->n_left->n_rval = RETREG(p->n_type);
ragge
1.1
351                 break;
352         }
gmcgarry
1.3
353
gmcgarry
1.8
354 #ifdef PCC_DEBUG
355         if (xdebug) {
356                 printf("clocal out: %p\n"p);
357                 fwalk(peprint0);
358         }
359 #endif
ragge
1.1
360
361         return(p);
362 }
363
364 void
365 myp2tree(NODE *p)
366 {
ragge
1.14
367         struct symtab *sp;
ragge
1.11
368
ragge
1.14
369         if (p->n_op != FCON
ragge
1.11
370                 return;
371
372         /* Write float constants to memory */
373  
gmcgarry
1.15
374         sp = IALLOC(sizeof(struct symtab));
ragge
1.14
375         sp->sclass = STATIC;
ragge
1.25
376         sp->sap = 0;
ragge
1.14
377         sp->slevel = 1/* fake numeric label */
378         sp->soffset = getlab();
379         sp->sflags = 0;
380         sp->stype = p->n_type;
381         sp->squal = (CON >> TSHIFT);
382
383         defloc(sp);
ragge
1.31
384         ninval(0tsize(sp->stypesp->sdfsp->sap), p);
ragge
1.14
385
ragge
1.11
386         p->n_op = NAME;
ragge
1.36
387         slval(p0);
ragge
1.14
388         p->n_sp = sp;
ragge
1.11
389
ragge
1.1
390 }
391
392 /*ARGSUSED*/
393 int
394 andable(NODE *p)
395 {
396         return(1);  /* all names can have & taken on them */
397 }
398
399 /*
400  * is an automatic variable of type t OK for a register variable
401  */
402 int
403 cisreg(TWORD t)
404 {
405         if (t == INT || t == UNSIGNED || t == LONG || t == ULONG)
406                 return(1);
407         return 0/* XXX - fix reg assignment in pftn.c */
408 }
409
410 /*
411  * Allocate off bits on the stack.  p is a tree that when evaluated
412  * is the multiply count for off, t is a NAME node where to write
413  * the allocated address.
414  */
415 void
416 spalloc(NODE *tNODE *pOFFSZ off)
417 {
418         NODE *sp;
gmcgarry
1.10
419         int nbytes = off / SZCHAR;
ragge
1.1
420
gmcgarry
1.10
421         p = buildtree(MULpbcon(nbytes));
422         p = buildtree(PLUSpbcon(7));
423         p = buildtree(ANDpbcon(~7));
424
425         /* subtract the size from sp */
426         sp = block(REGNILNILp->n_type00);
ragge
1.36
427         slval(sp0);
gmcgarry
1.10
428         sp->n_rval = SP;
429         ecomp(buildtree(MINUSEQspp));
ragge
1.1
430
431         /* save the address of sp */
ragge
1.22
432         sp = block(REGNILNILPTR+INTt->n_dft->n_ap);
gmcgarry
1.6
433         sp->n_rval = SP;
ragge
1.1
434         t->n_type = sp->n_type;
435         ecomp(buildtree(ASSIGNtsp)); /* Emit! */
436 }
437
438 /*
439  * print out a constant node
440  * mat be associated with a label
441  */
ragge
1.28
442 int
gmcgarry
1.2
443 ninval(CONSZ offint fszNODE *p)
ragge
1.1
444 {
gmcgarry
1.10
445         union { float fdouble dint i[2]; } u;
gmcgarry
1.3
446         struct symtab *q;
447         TWORD t;
448 #ifndef USE_GAS
gmcgarry
1.5
449         int ij;
gmcgarry
1.3
450 #endif
ragge
1.1
451
gmcgarry
1.3
452         t = p->n_type;
453         if (t > BTMASK)
ragge
1.28
454                 p->n_type = t = INT/* pointer */
gmcgarry
1.3
455
456         if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT)
457                 uerror("element not constant");
458
459         switch (t) {
460         case LONGLONG:
461         case ULONGLONG:
462 #ifdef USE_GAS
ragge
1.36
463                 printf("\t.dword %lld\n", (long long)glval(p));
gmcgarry
1.3
464 #else
ragge
1.37
465                 i = glval(p) >> 32;
466                 j = glval(p) & 0xffffffff;
gmcgarry
1.3
467                 p->n_type = INT;
gmcgarry
1.5
468                 if (bigendian) {
ragge
1.37
469                         slval(pj);
gmcgarry
1.5
470                         ninval(off32p);
ragge
1.37
471                         slval(pi);
gmcgarry
1.5
472                         ninval(off+3232p);
473                 } else {
ragge
1.37
474                         slval(pi);
gmcgarry
1.5
475                         ninval(off32p);
ragge
1.37
476                         slval(pj);
gmcgarry
1.5
477                         ninval(off+3232p);
478                 }
gmcgarry
1.3
479 #endif
480                 break;
481         case INT:
482         case UNSIGNED:
ragge
1.36
483                 printf("\t.word " CONFMT, (CONSZ)glval(p));
gmcgarry
1.3
484                 if ((q = p->n_sp) != NULL) {
ragge
1.18
485                         if ((q->sclass == STATIC && q->slevel > 0)) {
gmcgarry
1.3
486                                 printf("+" LABFMTq->soffset);
487                         } else
ragge
1.35
488                                 printf("+%s"getexname(q));
gmcgarry
1.3
489                 }
490                 printf("\n");
491                 break;
492         case SHORT:
493         case USHORT:
ragge
1.28
494                 astypnames[SHORT] = astypnames[USHORT] = "\t.half";
495                 return 0;
gmcgarry
1.3
496         case LDOUBLE:
497         case DOUBLE:
ragge
1.38
498                 u.d = (double)FCAST(p->n_dcon)->fp;
gmcgarry
1.9
499                 if (bigendian) {
gmcgarry
1.10
500                         printf("\t.word\t%d\n"u.i[0]);
501                         printf("\t.word\t%d\n"u.i[1]);
gmcgarry
1.9
502                 } else {
gmcgarry
1.10
503                         printf("\t.word\t%d\n"u.i[1]);
504                         printf("\t.word\t%d\n"u.i[0]);
gmcgarry
1.9
505                 }
gmcgarry
1.3
506                 break;
507         case FLOAT:
ragge
1.38
508                 u.f = (float)FCAST(p->n_dcon)->fp;
gmcgarry
1.3
509                 printf("\t.word\t0x%x\n"u.i[0]);
510                 break;
511         default:
ragge
1.28
512                 return 0;
gmcgarry
1.3
513         }
ragge
1.28
514         return 1;
ragge
1.1
515 }
516
517 /* make a name look like an external name in the local machine */
518 char *
519 exname(char *p)
520 {
521         if (p == NULL)
522                 return "";
523         return p;
524 }
525
526 /*
527  * map types which are not defined on the local machine
528  */
529 TWORD
530 ctype(TWORD type)
531 {
532         switch (BTYPE(type)) {
533         case LONG:
534                 MODTYPE(type,INT);
535                 break;
536
537         case ULONG:
538                 MODTYPE(type,UNSIGNED);
539
540         }
541         return (type);
542 }
543
544 void
545 calldec(NODE *pNODE *q
546 {
547 }
548
549 void
550 extdec(struct symtab *q)
551 {
552 }
553
ragge
1.14
554 /* make a common declaration for id, if reasonable */
555 void
556 defzero(struct symtab *sp)
557 {
558         int off;
559
ragge
1.22
560         off = tsize(sp->stypesp->sdfsp->sap);
ragge
1.14
561         off = (off+(SZCHAR-1))/SZCHAR;
562         printf("        .%scomm "sp->sclass == STATIC ? "l" : "");
563         if (sp->slevel == 0)
ragge
1.35
564                 printf("%s,0%o\n"getexname(sp), off);
ragge
1.14
565         else
566                 printf(LABFMT ",0%o\n"sp->soffsetoff);
567 }
568
569
570 #ifdef notdef
ragge
1.1
571 /* make a common declaration for id, if reasonable */
572 void
573 commdec(struct symtab *q)
574 {
575         int off;
576
577         off = tsize(q->stypeq->sdfq->ssue);
578         off = (off+(SZCHAR-1))/SZCHAR;
579
ragge
1.13
580         printf("        .comm %s,%d\n"exname(q->soname), off);
ragge
1.1
581 }
582
583 /* make a local common declaration for id, if reasonable */
584 void
585 lcommdec(struct symtab *q)
586 {
587         int off;
588
589         off = tsize(q->stypeq->sdfq->ssue);
590         off = (off+(SZCHAR-1))/SZCHAR;
591         if (q->slevel == 0)
ragge
1.13
592                 printf("\t.lcomm %s,%d\n"exname(q->soname), off);
ragge
1.1
593         else
gmcgarry
1.9
594                 printf("\t.lcomm " LABFMT ",%d\n"q->soffsetoff);
ragge
1.1
595 }
596
597 /*
598  * print a (non-prog) label.
599  */
600 void
601 deflab1(int label)
602 {
603         printf(LABFMT ":\n"label);
604 }
605
gmcgarry
1.9
606 /* ro-text, rw-data, ro-data, ro-strings */
607 static char *loctbl[] = { "text""data""rdata""rdata" };
ragge
1.1
608
609 void
610 setloc1(int locc)
611 {
gmcgarry
1.10
612         if (locc == lastloc && locc != STRNG)
ragge
1.1
613                 return;
gmcgarry
1.15
614         if (locc == RDATA && lastloc == STRNG)
gmcgarry
1.10
615                 return;
616
617         if (locc != lastloc) {
618                 lastloc = locc;
619                 printf("\t.%s\n"loctbl[locc]);
620         }
621
622         if (locc == STRNG)
623                 printf("\t.align 2\n");
ragge
1.1
624 }
ragge
1.14
625 #endif
gmcgarry
1.2
626
627 /*
gmcgarry
1.6
628  * va_start(ap, last) implementation.
629  *
630  * f is the NAME node for this builtin function.
631  * a is the argument list containing:
632  *         CM
633  *      ap   last
gmcgarry
1.7
634  *
635  * It turns out that this is easy on MIPS.  Just write the
636  * argument registers to the stack in va_arg_start() and
637  * use the traditional method of walking the stackframe.
gmcgarry
1.6
638  */
639 NODE *
ragge
1.33
640 mips_builtin_stdarg_start(const struct bitable *btNODE *a)
gmcgarry
1.6
641 {
gmcgarry
1.7
642         NODE *p, *q;
gmcgarry
1.6
643         int sz = 1;
644
645         /* check num args and type */
646         if (a == NULL || a->n_op != CM || a->n_left->n_op == CM ||
647             !ISPTR(a->n_left->n_type))
648                 goto bad;
649
650         /* must first deal with argument size; use int size */
651         p = a->n_right;
gmcgarry
1.7
652         if (p->n_type < INT) {
653                 /* round up to word */
ragge
1.22
654                 sz = SZINT / tsize(p->n_typep->n_dfp->n_ap);
gmcgarry
1.7
655         }
656
657         p = buildtree(ADDROFpNIL);  /* address of last arg */
658         p = optim(buildtree(PLUSpbcon(sz)));
659         q = block(NAMENILNILPTR+VOID00);
660         q = buildtree(CASTqp);
661         p = q->n_right;
662         nfree(q->n_left);
663         nfree(q);
664         p = buildtree(ASSIGNa->n_leftp);
665         nfree(a);
666
667         return p;
668
gmcgarry
1.6
669 bad:
gmcgarry
1.7
670         uerror("bad argument to __builtin_stdarg_start");
671         return bcon(0);
gmcgarry
1.6
672 }
673
674 NODE *
ragge
1.33
675 mips_builtin_va_arg(const struct bitable *btNODE *a)
gmcgarry
1.6
676 {
gmcgarry
1.7
677         NODE *p, *q, *r;
678         int sztmpnr;
679
680         /* check num args and type */
681         if (a == NULL || a->n_op != CM || a->n_left->n_op == CM ||
682             !ISPTR(a->n_left->n_type) || a->n_right->n_op != TYPE)
683                 goto bad;
684
gmcgarry
1.15
685         r = a->n_right;
gmcgarry
1.7
686
gmcgarry
1.15
687         /* get type size */
ragge
1.22
688         sz = tsize(r->n_typer->n_dfr->n_ap) / SZCHAR;
gmcgarry
1.9
689         if (sz < SZINT/SZCHAR) {
690                 werror("%s%s promoted to int when passed through ...",
691                         r->n_type & 1 ? "unsigned " : "",
692                         DEUNSIGN(r->n_type) == SHORT ? "short" : "char");
693                 sz = SZINT/SZCHAR;
694         }
gmcgarry
1.15
695
696         /* alignment */
697         p = tcopy(a->n_left);
698         if (sz > SZINT/SZCHAR && r->n_type != UNIONTY && r->n_type != STRTY) {
699                 p = buildtree(PLUSpbcon(7));
ragge
1.22
700                 p = block(ANDpbcon(-8), p->n_typep->n_dfp->n_ap);
gmcgarry
1.15
701         }
702
703         /* create a copy to a temp node */
ragge
1.22
704         q = tempnode(0p->n_typep->n_dfp->n_ap);
gmcgarry
1.15
705         tmpnr = regno(q);
706         p = buildtree(ASSIGNqp);
707
ragge
1.22
708         q = tempnode(tmpnrp->n_typep->n_df,p->n_ap);
gmcgarry
1.15
709         q = buildtree(PLUSqbcon(sz));
710         q = buildtree(ASSIGNa->n_leftq);
711
gmcgarry
1.7
712         q = buildtree(COMOPpq);
713
714         nfree(a->n_right);
715         nfree(a);
716
ragge
1.22
717         p = tempnode(tmpnrINCREF(r->n_type), r->n_dfr->n_ap);
gmcgarry
1.7
718         p = buildtree(UMULpNIL);
719         p = buildtree(COMOPqp);
720
721         return p;
722
723 bad:
724         uerror("bad argument to __builtin_va_arg");
725         return bcon(0);
gmcgarry
1.6
726 }
727
728 NODE *
ragge
1.33
729 mips_builtin_va_end(const struct bitable *btNODE *a)
gmcgarry
1.6
730 {
gmcgarry
1.7
731         tfree(a);
732         return bcon(0);
gmcgarry
1.6
733 }
734
735 NODE *
ragge
1.33
736 mips_builtin_va_copy(const struct bitable *btNODE *a)
gmcgarry
1.6
737 {
ragge
1.33
738         NODE *f;
739
gmcgarry
1.7
740         if (a == NULL || a->n_op != CM || a->n_left->n_op == CM)
741                 goto bad;
742         f = buildtree(ASSIGNa->n_lefta->n_right);
743         nfree(a);
gmcgarry
1.6
744         return f;
gmcgarry
1.7
745
746 bad:
747         uerror("bad argument to __buildtin_va_copy");
748         return bcon(0);
gmcgarry
1.6
749 }
gmcgarry
1.15
750
gmcgarry
1.17
751 static int constructor;
752 static int destructor;
753
ragge
1.13
754 /*
755  * Give target the opportunity of handling pragmas.
756  */
757 int
ragge
1.24
758 mypragma(char *str)
ragge
1.13
759 {
ragge
1.24
760
761         if (strcmp(str"tls") == 0) { 
gmcgarry
1.17
762                 uerror("thread-local storage not supported for this target");
763                 return 1;
764         } 
ragge
1.24
765         if (strcmp(str"constructor") == 0 || strcmp(str"init") == 0) {
gmcgarry
1.17
766                 constructor = 1;
767                 return 1;
768         }
ragge
1.24
769         if (strcmp(str"destructor") == 0 || strcmp(str"fini") == 0) {
gmcgarry
1.17
770                 destructor = 1;
771                 return 1;
772         }
773
gmcgarry
1.15
774         return 0;
775 }
ragge
1.13
776
777 /*
778  * Called when a identifier has been declared, to give target last word.
779  */
780 void
781 fixdef(struct symtab *sp)
782 {
gmcgarry
1.17
783         if ((constructor || destructor) && (sp->sclass != PARAM)) {
784                 printf("\t.section .%ctors,\"aw\",@progbits\n",
785                     constructor ? 'c' : 'd');
786                 printf("\t.p2align 2\n");
787                 printf("\t.long %s\n"exname(sp->sname));
gmcgarry
1.21
788                 printf("\t.previous\n");
gmcgarry
1.17
789                 constructor = destructor = 0;
790         }
791 }
792
793 void
794 pass1_lastchance(struct interpass *ip)
795 {
ragge
1.13
796 }
FishEye: Open Source License registered to PCC.
Your maintenance has expired. You can renew your license at http://www.atlassian.com/fisheye/renew
Atlassian FishEye, CVS analysis. (Version:1.6.3 Build:build-336 2008-11-04) - Administration - Page generated 2016-05-30 16:39 +0200