Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20090208163705

Diff

Diff from 1.19 to:

Annotations

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

Annotated File View

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