Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:gmcgarry:20071129055756

Diff

Diff from 1.7 to:

Annotations

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

Annotated File View

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