Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:gmcgarry:20071130232913

Diff

Diff from 1.8 to:

Annotations

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

Annotated File View

gmcgarry
1.8
1 /*      $Id: local.c,v 1.8 2007/11/30 23:29:13 gmcgarry 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  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 /*
30  * MIPS port by Jan Enoksson (janeno-1@student.ltu.se) and
31  * Simon Olsson (simols-1@student.ltu.se) 2005.
32  */
33
gmcgarry
1.7
34 #include <assert.h>
gmcgarry
1.3
35 #include "pass1.h"
ragge
1.1
36
gmcgarry
1.2
37 static int inbitsinval;
38
gmcgarry
1.3
39 /* this is called to do local transformations on
40  * an expression tree preparitory to its being
41  * written out in intermediate code.
42  */
ragge
1.1
43 NODE *
44 clocal(NODE *p)
45 {
gmcgarry
1.3
46         struct symtab *q;
47         NODE *r, *l;
48         int o;
gmcgarry
1.7
49         int m;
gmcgarry
1.6
50         TWORD ty;
gmcgarry
1.8
51         int tmpnrisptrvoid = 0;
ragge
1.1
52
gmcgarry
1.7
53 #ifdef PCC_DEBUG
54         if (xdebug) {
gmcgarry
1.8
55                 printf("clocal in: %p\n"p);
gmcgarry
1.7
56                 fwalk(peprint0);
57         }
58 #endif
gmcgarry
1.3
59
gmcgarry
1.6
60         switch (o = p->n_op) {
ragge
1.1
61
gmcgarry
1.8
62         case UCALL:
63         case CALL:
64         case STCALL:
65         case USTCALL:
66                 if (p->n_type == VOID)
67                         break;
68                 /*
69                  * if the function returns void*, ecode() invokes
70                  * delvoid() to convert it to uchar*.
71                  * We just let this happen on the ASSIGN to the temp,
72                  * and cast the pointer back to void* on access
73                  * from the temp.
74                  */
75                 if (p->n_type == PTR+VOID)
76                         isptrvoid = 1;
77                 r = tempnode(0p->n_typep->n_dfp->n_sue);
78                 tmpnr = r->n_lval;
79                 r = block(ASSIGNrpp->n_typep->n_dfp->n_sue);
80                 ecomp(r);
81                 p = tempnode(tmpnrr->n_typer->n_dfr->n_sue);
82                 if (isptrvoid) {
83                         p = block(PCONVpNILPTR+VOID,
84                             p->n_dfMKSUE(PTR+VOID));
85                 }
86                 break;
87
ragge
1.1
88         case NAME:
89                 if ((q = p->n_sp) == NULL)
90                         return p/* Nothing to care about */
91
92                 switch (q->sclass) {
93
94                 case PARAM:
95                 case AUTO:
96                         /* fake up a structure reference */
97                         r = block(REGNILNILPTR+STRTY00);
98                         r->n_lval = 0;
gmcgarry
1.3
99                         r->n_rval = FP;
ragge
1.1
100                         p = stref(block(STREFrp000));
101                         break;
102
103                 case STATIC:
104                         if (q->slevel == 0)
105                                 break;
106                         p->n_lval = 0;
107                         p->n_sp = q;
108                         break;
109
110                 case REGISTER:
111                         p->n_op = REG;
112                         p->n_lval = 0;
113                         p->n_rval = q->soffset;
114                         break;
115
gmcgarry
1.7
116                 }
ragge
1.1
117                 break;
118
119         case FUNARG:
120                 /* Args smaller than int are given as int */
121                 if (p->n_type != CHAR && p->n_type != UCHAR && 
122                     p->n_type != SHORT && p->n_type != USHORT)
123                         break;
124                 p->n_left = block(SCONVp->n_leftNILINT0MKSUE(INT));
125                 p->n_type = INT;
126                 p->n_sue = MKSUE(INT);
127                 p->n_rval = SZINT;
128                 break;
129
130         case CBRANCH:
131                 l = p->n_left;
132
133                 /*
134                  * Remove unneccessary conversion ops.
135                  */
136                 if (clogop(l->n_op) && l->n_left->n_op == SCONV) {
137                         if (coptype(l->n_op) != BITYPE)
138                                 break;
139                         if (l->n_right->n_op == ICON) {
140                                 r = l->n_left->n_left;
141                                 if (r->n_type >= FLOAT && r->n_type <= LDOUBLE)
142                                         break;
143                                 /* Type must be correct */
gmcgarry
1.6
144                                 ty = r->n_type;
ragge
1.1
145                                 nfree(l->n_left);
146                                 l->n_left = r;
gmcgarry
1.6
147                                 l->n_type = ty;
148                                 l->n_right->n_type = ty;
ragge
1.1
149                         }
150 #if 0
151                           else if (l->n_right->n_op == SCONV &&
152                             l->n_left->n_type == l->n_right->n_type) {
153                                 r = l->n_left->n_left;
154                                 nfree(l->n_left);
155                                 l->n_left = r;
156                                 r = l->n_right->n_left;
157                                 nfree(l->n_right);
158                                 l->n_right = r;
159                         }
160 #endif
161                 }
162                 break;
163
164         case PCONV:
gmcgarry
1.7
165                 /* Remove redundant PCONV's. Be careful */
ragge
1.1
166                 l = p->n_left;
gmcgarry
1.7
167                 if (l->n_op == ICON) {
168                         l->n_lval = (unsigned)l->n_lval;
169                         goto delp;
170                 }
gmcgarry
1.8
171                 if (l->n_type < INT || DEUNSIGN(l->n_type) == LONGLONG) {
gmcgarry
1.7
172                         /* float etc? */
173                         p->n_left = block(SCONVlNIL,
174                             UNSIGNED0MKSUE(UNSIGNED));
175                         break;
176                 }
177                 /* if left is SCONV, cannot remove */
178                 if (l->n_op == SCONV)
179                         break;
180
181                 /* avoid ADDROF TEMP */
182                 if (l->n_op == ADDROF && l->n_left->n_op == TEMP)
ragge
1.1
183                         break;
gmcgarry
1.7
184
185                 /* if conversion to another pointer type, just remove */
186                 if (p->n_type > BTMASK && l->n_type > BTMASK)
187                         goto delp;
188                 break;
189
190         delp:   l->n_type = p->n_type;
ragge
1.1
191                 l->n_qual = p->n_qual;
192                 l->n_df = p->n_df;
193                 l->n_sue = p->n_sue;
194                 nfree(p);
195                 p = l;
196                 break;
197
198         case SCONV:
199                 l = p->n_left;
200
201                 if (p->n_type == l->n_type) {
202                         nfree(p);
gmcgarry
1.8
203                         p = l;
204                         break;
ragge
1.1
205                 }
206
207                 if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 &&
208                     btdims[p->n_type].suesize == btdims[l->n_type].suesize) {
209                         if (p->n_type != FLOAT && p->n_type != DOUBLE &&
210                             l->n_type != FLOAT && l->n_type != DOUBLE &&
211                             l->n_type != LDOUBLE && p->n_type != LDOUBLE) {
gmcgarry
1.8
212                                 if (l->n_op == NAME || l->n_op == UMUL ||
213                                     l->n_op == TEMP) {
ragge
1.1
214                                         l->n_type = p->n_type;
215                                         nfree(p);
gmcgarry
1.8
216                                         p = l;
217                                         break;
ragge
1.1
218                                 }
219                         }
220                 }
221
gmcgarry
1.8
222                 if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT &&
223                     coptype(l->n_op) == BITYPE) {
224                         l->n_type = p->n_type;
225                         nfree(p);
226                         p = l;
227                 }
228
229                 if (DEUNSIGN(p->n_type) == SHORT &&
230                     DEUNSIGN(l->n_type) == SHORT) {
ragge
1.1
231                         nfree(p);
gmcgarry
1.8
232                         p = l;
ragge
1.1
233                 }
234
gmcgarry
1.8
235                 if ((DEUNSIGN(p->n_type) == CHAR ||
236                     DEUNSIGN(p->n_type) == SHORT) &&
237                     (l->n_type == FLOAT || l->n_type == DOUBLE ||
238                     l->n_type == LDOUBLE)) {
239                         p = block(SCONVpNILp->n_typep->n_dfp->n_sue);
240                         p->n_left->n_type = INT;
241                         break;
242                 }
243
244
ragge
1.1
245                 o = l->n_op;
246                 m = p->n_type;
247
248                 if (o == ICON) {
249                         CONSZ val = l->n_lval;
250
251                         if (!ISPTR(m)) /* Pointers don't need to be conv'd */
252                             switch (m) {
253                         case CHAR:
254                                 l->n_lval = (char)val;
255                                 break;
256                         case UCHAR:
257                                 l->n_lval = val & 0377;
258                                 break;
259                         case SHORT:
260                                 l->n_lval = (short)val;
261                                 break;
262                         case USHORT:
263                                 l->n_lval = val & 0177777;
264                                 break;
265                         case ULONG:
266                         case UNSIGNED:
267                                 l->n_lval = val & 0xffffffff;
268                                 break;
269                         case LONG:
270                         case INT:
271                                 l->n_lval = (int)val;
272                                 break;
273                         case LONGLONG:
274                                 l->n_lval = (long long)val;
275                                 break;
276                         case ULONGLONG:
277                                 l->n_lval = val;
278                                 break;
279                         case VOID:
280                                 break;
281                         case LDOUBLE:
282                         case DOUBLE:
283                         case FLOAT:
284                                 l->n_op = FCON;
285                                 l->n_dcon = val;
286                                 break;
287                         default:
288                                 cerror("unknown type %d"m);
289                         }
290                         l->n_type = m;
291                         nfree(p);
292                         p = l;
293                 }
294                 break;
295
296         case MOD:
297         case DIV:
298                 if (o == DIV && p->n_type != CHAR && p->n_type != SHORT)
299                         break;
300                 if (o == MOD && p->n_type != CHAR && p->n_type != SHORT)
301                         break;
302                 /* make it an int division by inserting conversions */
303                 p->n_left = block(SCONVp->n_leftNILINT0MKSUE(INT));
304                 p->n_right = block(SCONVp->n_rightNILINT0MKSUE(INT));
305                 p = block(SCONVpNILp->n_type0MKSUE(p->n_type));
306                 p->n_left->n_type = INT;
307                 break;
308
309         case PMCONV:
310         case PVCONV:
311                 ifp->n_right->n_op != ICON ) cerror"bad conversion"0);
312                 nfree(p);
gmcgarry
1.8
313                 p = buildtree(o==PMCONV?MUL:DIVp->n_leftp->n_right);
314                 break;
ragge
1.1
315
316         case FORCE:
317                 /* put return value in return reg */
318                 p->n_op = ASSIGN;
319                 p->n_right = p->n_left;
gmcgarry
1.2
320                 p->n_left = block(REGNILNILp->n_type0MKSUE(INT));
gmcgarry
1.3
321                 p->n_left->n_rval = RETREG(p->n_type);
ragge
1.1
322                 break;
323         }
gmcgarry
1.3
324
gmcgarry
1.8
325 #ifdef PCC_DEBUG
326         if (xdebug) {
327                 printf("clocal out: %p\n"p);
328                 fwalk(peprint0);
329         }
330 #endif
ragge
1.1
331
332         return(p);
333 }
334
335 void
336 myp2tree(NODE *p)
337 {
338 }
339
340 /*ARGSUSED*/
341 int
342 andable(NODE *p)
343 {
344         return(1);  /* all names can have & taken on them */
345 }
346
347 /*
348  * at the end of the arguments of a ftn, set the automatic offset
349  */
350 void
351 cendarg()
352 {
353         autooff = AUTOINIT;
354 }
355
356 /*
357  * is an automatic variable of type t OK for a register variable
358  */
359 int
360 cisreg(TWORD t)
361 {
362         if (t == INT || t == UNSIGNED || t == LONG || t == ULONG)
363                 return(1);
364         return 0/* XXX - fix reg assignment in pftn.c */
365 }
366
367 /*
368  * return a node, for structure references, which is suitable for
369  * being added to a pointer of type t, in order to be off bits offset
370  * into a structure
371  * t, d, and s are the type, dimension offset, and sizeoffset
372  * Be careful about only handling first-level pointers, the following
373  * indirections must be fullword.
374  */
375 NODE *
376 offcon(OFFSZ offTWORD tunion dimfun *dstruct suedef *sue)
377 {
gmcgarry
1.3
378         NODE *p;
ragge
1.1
379
380         if (xdebug)
381                 printf("offcon: OFFSZ %lld type %x dim %p siz %d\n",
382                     offtdsue->suesize);
383
gmcgarry
1.3
384         p = bcon(off/SZCHAR);
385         return p;
ragge
1.1
386 }
387
388 /*
389  * Allocate off bits on the stack.  p is a tree that when evaluated
390  * is the multiply count for off, t is a NAME node where to write
391  * the allocated address.
392  */
393 void
394 spalloc(NODE *tNODE *pOFFSZ off)
395 {
396         NODE *sp;
397
398         if ((off % SZINT) == 0)
399                 p =  buildtree(MULpbcon(off/SZINT));
400         else if ((off % SZSHORT) == 0) {
401                 p = buildtree(MULpbcon(off/SZSHORT));
402                 p = buildtree(PLUSpbcon(1));
403                 p = buildtree(RSpbcon(1));
404         } else if ((off % SZCHAR) == 0) {
405                 p = buildtree(MULpbcon(off/SZCHAR));
406                 p = buildtree(PLUSpbcon(3));
407                 p = buildtree(RSpbcon(2));
408         } else
409                 cerror("roundsp");
410
411         /* save the address of sp */
412         sp = block(REGNILNILPTR+INTt->n_dft->n_sue);
413         sp->n_lval = 0;
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         /* add the size to sp */
419         sp = block(REGNILNILp->n_type00);
420         sp->n_lval = 0;
gmcgarry
1.6
421         sp->n_rval = SP;
ragge
1.1
422         ecomp(buildtree(PLUSEQspp));
423 }
424
425 /*
426  * print out a constant node
427  * mat be associated with a label
428  */
429 void
gmcgarry
1.2
430 ninval(CONSZ offint fszNODE *p)
ragge
1.1
431 {
gmcgarry
1.3
432         union { float fdouble dlong double lint i[3]; } u;
433         struct symtab *q;
434         TWORD t;
435 #ifndef USE_GAS
gmcgarry
1.5
436         int ij;
gmcgarry
1.3
437 #endif
ragge
1.1
438
gmcgarry
1.3
439         t = p->n_type;
440         if (t > BTMASK)
441                 t = INT/* pointer */
442
443         if (p->n_op != ICON && p->n_op != FCON)
444                 cerror("ninval: init node not constant");
445
446         if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT)
447                 uerror("element not constant");
448
449         switch (t) {
450         case LONGLONG:
451         case ULONGLONG:
452 #ifdef USE_GAS
453                 printf("\t.dword 0x%llx\n", (long long)p->n_lval);
454 #else
gmcgarry
1.5
455                 i = p->n_lval >> 32;
456                 j = p->n_lval & 0xffffffff;
gmcgarry
1.3
457                 p->n_type = INT;
gmcgarry
1.5
458                 if (bigendian) {
459                         p->n_lval = j;
460                         ninval(off32p);
461                         p->n_lval = i;
462                         ninval(off+3232p);
463                 } else {
464                         p->n_lval = i;
465                         ninval(off32p);
466                         p->n_lval = j;
467                         ninval(off+3232p);
468                 }
gmcgarry
1.3
469 #endif
470                 break;
471         case BOOL:
472                 if (p->n_lval > 1)
473                         p->n_lval = p->n_lval != 0;
474                 /* FALLTHROUGH */
475         case INT:
476         case UNSIGNED:
477                 printf("\t.word 0x%x", (int)p->n_lval);
478                 if ((q = p->n_sp) != NULL) {
479                         if ((q->sclass == STATIC && q->slevel > 0) ||
480                             q->sclass == ILABEL) {
481                                 printf("+" LABFMTq->soffset);
482                         } else
483                                 printf("+%s"exname(q->sname));
484                 }
485                 printf("\n");
486                 break;
487         case SHORT:
488         case USHORT:
489                 printf("\t.half 0x%x\n", (int)p->n_lval & 0xffff);
490                 break;
491         case CHAR:
492         case UCHAR:
493                 printf("\t.byte %d\n", (int)p->n_lval & 0xff);
494                 break;
495         case LDOUBLE:
496                 u.i[2] = 0;
497                 u.l = (long double)p->n_dcon;
498                 printf("\t.word\t0x%x,0x%x,0x%x\n"u.i[0], u.i[1], u.i[2]);
499                 break;
500         case DOUBLE:
501                 u.d = (double)p->n_dcon;
502                 printf("\t.word\t0x%x\n"u.i[0]);
503                 printf("\t.word\t0x%x\n"u.i[1]);
504                 break;
505         case FLOAT:
506                 u.f = (float)p->n_dcon;
507                 printf("\t.word\t0x%x\n"u.i[0]);
508                 break;
509         default:
510                 cerror("ninval");
511         }
ragge
1.1
512 }
513
514 /* make a name look like an external name in the local machine */
515 char *
516 exname(char *p)
517 {
518         if (p == NULL)
519                 return "";
520         return p;
521 }
522
523 /*
524  * map types which are not defined on the local machine
525  */
526 TWORD
527 ctype(TWORD type)
528 {
529         switch (BTYPE(type)) {
530         case LONG:
531                 MODTYPE(type,INT);
532                 break;
533
534         case ULONG:
535                 MODTYPE(type,UNSIGNED);
536
537         }
538         return (type);
539 }
540
541 /* curid is a variable which is defined but
542  * is not initialized (and not a function );
543  * This routine returns the storage class for an uninitialized declaration
544  */
545 int
546 noinit()
547 {
548         return(EXTERN);
549 }
550
551 void
552 calldec(NODE *pNODE *q
553 {
554 }
555
556 void
557 extdec(struct symtab *q)
558 {
559 }
560
561 /* make a common declaration for id, if reasonable */
562 void
563 commdec(struct symtab *q)
564 {
565         int off;
566
567         off = tsize(q->stypeq->sdfq->ssue);
568         off = (off+(SZCHAR-1))/SZCHAR;
569
570 #ifdef GCC_COMPAT
571         printf("        .comm %s,0%o\n"gcc_findname(q), off);
572 #else
573         printf("        .comm %s,0%o\n"exname(q->sname), off);
574 #endif
575 }
576
577 /* make a local common declaration for id, if reasonable */
578 void
579 lcommdec(struct symtab *q)
580 {
581         int off;
582
583         off = tsize(q->stypeq->sdfq->ssue);
584         off = (off+(SZCHAR-1))/SZCHAR;
585         if (q->slevel == 0)
586 #ifdef GCC_COMPAT
gmcgarry
1.3
587                 printf("\t.lcomm %s,0%o\n"gcc_findname(q), off);
ragge
1.1
588 #else
gmcgarry
1.3
589                 printf("\t.lcomm %s,0%o\n"exname(q->sname), off);
ragge
1.1
590 #endif
591         else
gmcgarry
1.3
592                 printf("\t.lcomm " LABFMT ",0%o\n"q->soffsetoff);
ragge
1.1
593 }
594
595 /*
596  * print a (non-prog) label.
597  */
598 void
599 deflab1(int label)
600 {
601         printf(LABFMT ":\n"label);
602 }
603
gmcgarry
1.6
604 /* ro-text, ro-data, rw-data, ro-strings */
605 static char *loctbl[] = { "text""rdata""data""rdata" };
ragge
1.1
606
607 void
608 setloc1(int locc)
609 {
gmcgarry
1.6
610         if ((locc == lastloc) || (lastloc == DATA && locc == STRNG) ||
611             (locc == STRNG && lastloc == DATA))
ragge
1.1
612                 return;
613         lastloc = locc;
gmcgarry
1.3
614         printf("\t.%s\n"loctbl[locc]);
ragge
1.1
615 }
gmcgarry
1.2
616
617 /*
618  * Initialize a bitfield.
619  */
620 void
621 infld(CONSZ offint fszCONSZ val)
622 {
623         if (idebug)
624                 printf("infld off %lld, fsz %d, val %lld inbits %d\n",
625                     offfszvalinbits);
626         val &= (1 << fsz)-1;
627         while (fsz + inbits >= SZCHAR) {
628                 inval |= (val << inbits);
629                 printf("\t.byte %d\n"inval & 255);
630                 fsz -= (SZCHAR - inbits);
631                 val >>= (SZCHAR - inbits);
632                 inval = inbits = 0;
633         }
634         if (fsz) {
635                 inval |= (val << inbits);
636                 inbits += fsz;
637         }
638 }
639
640 /*
641  * set fsz bits in sequence to zero.
642  */
643 void
644 zbits(OFFSZ offint fsz)
645 {
646         int m;
647
648         if (idebug)
649                 printf("zbits off %lld, fsz %d inbits %d\n"offfszinbits);
650         if ((m = (inbits % SZCHAR))) {
651                 m = SZCHAR - m;
652                 if (fsz < m) {
653                         inbits += fsz;
654                         return;
655                 } else {
656                         fsz -= m;
657                         printf("\t.byte %d\n"inval);
658                         inval = inbits = 0;
659                 }
660         }
661         if (fsz >= SZCHAR) {
662                 printf("\t.zero %d\n"fsz/SZCHAR);
663                 fsz -= (fsz/SZCHAR) * SZCHAR;
664         }
665         if (fsz) {
666                 inval = 0;
667                 inbits = fsz;
668         }
669 }
gmcgarry
1.6
670
671 /*
672  * va_start(ap, last) implementation.
673  *
674  * f is the NAME node for this builtin function.
675  * a is the argument list containing:
676  *         CM
677  *      ap   last
gmcgarry
1.7
678  *
679  * It turns out that this is easy on MIPS.  Just write the
680  * argument registers to the stack in va_arg_start() and
681  * use the traditional method of walking the stackframe.
gmcgarry
1.6
682  */
683 NODE *
684 mips_builtin_stdarg_start(NODE *fNODE *a)
685 {
gmcgarry
1.7
686         NODE *p, *q;
gmcgarry
1.6
687         int sz = 1;
gmcgarry
1.7
688         int i;
gmcgarry
1.6
689
690         /* check num args and type */
691         if (a == NULL || a->n_op != CM || a->n_left->n_op == CM ||
692             !ISPTR(a->n_left->n_type))
693                 goto bad;
694
gmcgarry
1.7
695         /*
696          * look at the offset of the last org to calculate the
697          * number of remain registers that need to be written
698          * to the stack.
699          */
700         if (xtemps) {
701                 for (i = 0i < nargregsi++) {
702                         q = block(REGNILNILPTR+INT0MKSUE(INT));
703                         q->n_rval = A0 + i;
704                         p = block(REGNILNILPTR+INT0MKSUE(INT));
705                         p->n_rval = SP;
706                         p = block(PLUSpbcon(ARGINIT+i), PTR+INT0MKSUE(INT));
707                         p = buildtree(UMULpNIL);
708                         p = buildtree(ASSIGNpq);
709                         ecomp(p);
710                 }
711         }
712
gmcgarry
1.6
713         /* must first deal with argument size; use int size */
714         p = a->n_right;
gmcgarry
1.7
715         if (p->n_type < INT) {
716                 /* round up to word */
gmcgarry
1.6
717                 sz = SZINT / tsize(p->n_typep->n_dfp->n_sue);
gmcgarry
1.7
718         }
719
720         /*
721          * Once again, if xtemps, the register is written to a
722          * temp.  We cannot take the address of the temp and
723          * walk from there.
724          *
725          * No solution at the moment...
726          */
727         assert(!xtemps);
728
729         p = buildtree(ADDROFpNIL);  /* address of last arg */
730         p = optim(buildtree(PLUSpbcon(sz)));
731         q = block(NAMENILNILPTR+VOID00);
732         q = buildtree(CASTqp);
733         p = q->n_right;
734         nfree(q->n_left);
735         nfree(q);
736         p = buildtree(ASSIGNa->n_leftp);
737         tfree(f);
738         nfree(a);
739
740         return p;
741
gmcgarry
1.6
742 bad:
gmcgarry
1.7
743         uerror("bad argument to __builtin_stdarg_start");
744         return bcon(0);
gmcgarry
1.6
745 }
746
747 NODE *
748 mips_builtin_va_arg(NODE *fNODE *a)
749 {
gmcgarry
1.7
750         NODE *p, *q, *r;
751         int sztmpnr;
752
753         /* check num args and type */
754         if (a == NULL || a->n_op != CM || a->n_left->n_op == CM ||
755             !ISPTR(a->n_left->n_type) || a->n_right->n_op != TYPE)
756                 goto bad;
757
758         /* create a copy to a temp node */
759         p = tcopy(a->n_left);
760         q = tempnode(0p->n_typep->n_dfp->n_sue);
761         tmpnr = q->n_lval;
762         p = buildtree(ASSIGNqp);
763
764         r = a->n_right;
765         sz = tsize(r->n_typer->n_dfr->n_sue) / SZCHAR;
766         q = buildtree(PLUSEQa->n_leftbcon(sz));
767         q = buildtree(COMOPpq);
768
769         nfree(a->n_right);
770         nfree(a);
771         nfree(f); 
772
773         p = tempnode(tmpnrINCREF(r->n_type), r->n_dfr->n_sue);
774         p = buildtree(UMULpNIL);
775         p = buildtree(COMOPqp);
776
777         return p;
778
779 bad:
780         uerror("bad argument to __builtin_va_arg");
781         return bcon(0);
gmcgarry
1.6
782 }
783
784 NODE *
785 mips_builtin_va_end(NODE *fNODE *a)
786 {
gmcgarry
1.7
787         tfree(f);
788         tfree(a);
789         return bcon(0);
gmcgarry
1.6
790 }
791
792 NODE *
793 mips_builtin_va_copy(NODE *fNODE *a)
794 {
gmcgarry
1.7
795         if (a == NULL || a->n_op != CM || a->n_left->n_op == CM)
796                 goto bad;
797         tfree(f);
798         f = buildtree(ASSIGNa->n_lefta->n_right);
799         nfree(a);
gmcgarry
1.6
800         return f;
gmcgarry
1.7
801
802 bad:
803         uerror("bad argument to __buildtin_va_copy");
804         return bcon(0);
gmcgarry
1.6
805 }
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 2014-10-30 16:57 +0100