Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20110605102909

Diff

Diff from 1.29 to:

Annotations

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

Annotated File View

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