Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20081214211658

Diff

Diff from 1.18 to:

Annotations

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

Annotated File View

ragge
1.18
1 /*      $Id: local.c,v 1.18 2008/12/14 21:16:58 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.13
519                                 printf("+%s"exname(q->soname));
gmcgarry
1.3
520                 }
521                 printf("\n");
522                 break;
523         case SHORT:
524         case USHORT:
gmcgarry
1.10
525                 printf("\t.half %d\n", (int)p->n_lval & 0xffff);
gmcgarry
1.3
526                 break;
527         case CHAR:
528         case UCHAR:
529                 printf("\t.byte %d\n", (int)p->n_lval & 0xff);
530                 break;
531         case LDOUBLE:
532         case DOUBLE:
533                 u.d = (double)p->n_dcon;
gmcgarry
1.9
534                 if (bigendian) {
gmcgarry
1.10
535                         printf("\t.word\t%d\n"u.i[0]);
536                         printf("\t.word\t%d\n"u.i[1]);
gmcgarry
1.9
537                 } else {
gmcgarry
1.10
538                         printf("\t.word\t%d\n"u.i[1]);
539                         printf("\t.word\t%d\n"u.i[0]);
gmcgarry
1.9
540                 }
gmcgarry
1.3
541                 break;
542         case FLOAT:
543                 u.f = (float)p->n_dcon;
544                 printf("\t.word\t0x%x\n"u.i[0]);
545                 break;
546         default:
547                 cerror("ninval");
548         }
ragge
1.1
549 }
550
551 /* make a name look like an external name in the local machine */
552 char *
553 exname(char *p)
554 {
555         if (p == NULL)
556                 return "";
557         return p;
558 }
559
560 /*
561  * map types which are not defined on the local machine
562  */
563 TWORD
564 ctype(TWORD type)
565 {
566         switch (BTYPE(type)) {
567         case LONG:
568                 MODTYPE(type,INT);
569                 break;
570
571         case ULONG:
572                 MODTYPE(type,UNSIGNED);
573
574         }
575         return (type);
576 }
577
578 /* curid is a variable which is defined but
579  * is not initialized (and not a function );
580  * This routine returns the storage class for an uninitialized declaration
581  */
582 int
583 noinit()
584 {
585         return(EXTERN);
586 }
587
588 void
589 calldec(NODE *pNODE *q
590 {
591 }
592
593 void
594 extdec(struct symtab *q)
595 {
596 }
597
ragge
1.14
598 /*
599  * Print out a string of characters.
600  * Assume that the assembler understands C-style escape
601  * sequences.
602  */
603 void
604 instring(struct symtab *sp)
605 {
606         char *s, *str;
607
608         defloc(sp);
609         str = sp->sname;
610
611         /* be kind to assemblers and avoid long strings */
612         printf("\t.ascii \"");
613         for (s = str; *s != 0; ) {
614                 if (*s++ == '\\') {
615                         (void)esccon(&s);
616                 }
617                 if (s - str > 60) {
618                         fwrite(str1s - strstdout);
619                         printf("\"\n\t.ascii \"");
620                         str = s;
621                 }
622         }
623         fwrite(str1s - strstdout);
624         printf("\\0\"\n");
625 }
626
627 /*
628  * Print out a wide string by calling ninval().
629  */
630 void
631 inwstring(struct symtab *sp)
632 {
633         char *s = sp->sname;
634         NODE *p;
635
636         defloc(sp);
gmcgarry
1.17
637         p = xbcon(0NULLWCHAR_TYPE);
ragge
1.14
638         do {
639                 if (*s++ == '\\')
640                         p->n_lval = esccon(&s);
641                 else
642                         p->n_lval = (unsigned char)s[-1];
643                 ninval(0, (MKSUE(WCHAR_TYPE))->suesizep);
644         } while (s[-1] != 0);
645         nfree(p);
646 }
647
648 /* make a common declaration for id, if reasonable */
649 void
650 defzero(struct symtab *sp)
651 {
652         int off;
653
654         off = tsize(sp->stypesp->sdfsp->ssue);
655         off = (off+(SZCHAR-1))/SZCHAR;
656         printf("        .%scomm "sp->sclass == STATIC ? "l" : "");
657         if (sp->slevel == 0)
658                 printf("%s,0%o\n"exname(sp->soname), off);
659         else
660                 printf(LABFMT ",0%o\n"sp->soffsetoff);
661 }
662
663
664 #ifdef notdef
ragge
1.1
665 /* make a common declaration for id, if reasonable */
666 void
667 commdec(struct symtab *q)
668 {
669         int off;
670
671         off = tsize(q->stypeq->sdfq->ssue);
672         off = (off+(SZCHAR-1))/SZCHAR;
673
ragge
1.13
674         printf("        .comm %s,%d\n"exname(q->soname), off);
ragge
1.1
675 }
676
677 /* make a local common declaration for id, if reasonable */
678 void
679 lcommdec(struct symtab *q)
680 {
681         int off;
682
683         off = tsize(q->stypeq->sdfq->ssue);
684         off = (off+(SZCHAR-1))/SZCHAR;
685         if (q->slevel == 0)
ragge
1.13
686                 printf("\t.lcomm %s,%d\n"exname(q->soname), off);
ragge
1.1
687         else
gmcgarry
1.9
688                 printf("\t.lcomm " LABFMT ",%d\n"q->soffsetoff);
ragge
1.1
689 }
690
691 /*
692  * print a (non-prog) label.
693  */
694 void
695 deflab1(int label)
696 {
697         printf(LABFMT ":\n"label);
698 }
699
gmcgarry
1.9
700 /* ro-text, rw-data, ro-data, ro-strings */
701 static char *loctbl[] = { "text""data""rdata""rdata" };
ragge
1.1
702
703 void
704 setloc1(int locc)
705 {
gmcgarry
1.10
706         if (locc == lastloc && locc != STRNG)
ragge
1.1
707                 return;
gmcgarry
1.15
708         if (locc == RDATA && lastloc == STRNG)
gmcgarry
1.10
709                 return;
710
711         if (locc != lastloc) {
712                 lastloc = locc;
713                 printf("\t.%s\n"loctbl[locc]);
714         }
715
716         if (locc == STRNG)
717                 printf("\t.align 2\n");
ragge
1.1
718 }
ragge
1.14
719 #endif
gmcgarry
1.2
720
721 /*
722  * Initialize a bitfield.
723  */
724 void
725 infld(CONSZ offint fszCONSZ val)
726 {
727         if (idebug)
728                 printf("infld off %lld, fsz %d, val %lld inbits %d\n",
729                     offfszvalinbits);
730         val &= (1 << fsz)-1;
731         while (fsz + inbits >= SZCHAR) {
732                 inval |= (val << inbits);
733                 printf("\t.byte %d\n"inval & 255);
734                 fsz -= (SZCHAR - inbits);
735                 val >>= (SZCHAR - inbits);
736                 inval = inbits = 0;
737         }
738         if (fsz) {
739                 inval |= (val << inbits);
740                 inbits += fsz;
741         }
742 }
743
744 /*
745  * set fsz bits in sequence to zero.
746  */
747 void
748 zbits(OFFSZ offint fsz)
749 {
750         int m;
751
752         if (idebug)
753                 printf("zbits off %lld, fsz %d inbits %d\n"offfszinbits);
754         if ((m = (inbits % SZCHAR))) {
755                 m = SZCHAR - m;
756                 if (fsz < m) {
757                         inbits += fsz;
758                         return;
759                 } else {
760                         fsz -= m;
761                         printf("\t.byte %d\n"inval);
762                         inval = inbits = 0;
763                 }
764         }
765         if (fsz >= SZCHAR) {
766                 printf("\t.zero %d\n"fsz/SZCHAR);
767                 fsz -= (fsz/SZCHAR) * SZCHAR;
768         }
769         if (fsz) {
770                 inval = 0;
771                 inbits = fsz;
772         }
773 }
gmcgarry
1.6
774
775 /*
776  * va_start(ap, last) implementation.
777  *
778  * f is the NAME node for this builtin function.
779  * a is the argument list containing:
780  *         CM
781  *      ap   last
gmcgarry
1.7
782  *
783  * It turns out that this is easy on MIPS.  Just write the
784  * argument registers to the stack in va_arg_start() and
785  * use the traditional method of walking the stackframe.
gmcgarry
1.6
786  */
787 NODE *
788 mips_builtin_stdarg_start(NODE *fNODE *a)
789 {
gmcgarry
1.7
790         NODE *p, *q;
gmcgarry
1.6
791         int sz = 1;
792
793         /* check num args and type */
794         if (a == NULL || a->n_op != CM || a->n_left->n_op == CM ||
795             !ISPTR(a->n_left->n_type))
796                 goto bad;
797
798         /* must first deal with argument size; use int size */
799         p = a->n_right;
gmcgarry
1.7
800         if (p->n_type < INT) {
801                 /* round up to word */
gmcgarry
1.6
802                 sz = SZINT / tsize(p->n_typep->n_dfp->n_sue);
gmcgarry
1.7
803         }
804
805         p = buildtree(ADDROFpNIL);  /* address of last arg */
806         p = optim(buildtree(PLUSpbcon(sz)));
807         q = block(NAMENILNILPTR+VOID00);
808         q = buildtree(CASTqp);
809         p = q->n_right;
810         nfree(q->n_left);
811         nfree(q);
812         p = buildtree(ASSIGNa->n_leftp);
813         tfree(f);
814         nfree(a);
815
816         return p;
817
gmcgarry
1.6
818 bad:
gmcgarry
1.7
819         uerror("bad argument to __builtin_stdarg_start");
820         return bcon(0);
gmcgarry
1.6
821 }
822
823 NODE *
824 mips_builtin_va_arg(NODE *fNODE *a)
825 {
gmcgarry
1.7
826         NODE *p, *q, *r;
827         int sztmpnr;
828
829         /* check num args and type */
830         if (a == NULL || a->n_op != CM || a->n_left->n_op == CM ||
831             !ISPTR(a->n_left->n_type) || a->n_right->n_op != TYPE)
832                 goto bad;
833
gmcgarry
1.15
834         r = a->n_right;
gmcgarry
1.7
835
gmcgarry
1.15
836         /* get type size */
gmcgarry
1.7
837         sz = tsize(r->n_typer->n_dfr->n_sue) / SZCHAR;
gmcgarry
1.9
838         if (sz < SZINT/SZCHAR) {
839                 werror("%s%s promoted to int when passed through ...",
840                         r->n_type & 1 ? "unsigned " : "",
841                         DEUNSIGN(r->n_type) == SHORT ? "short" : "char");
842                 sz = SZINT/SZCHAR;
843         }
gmcgarry
1.15
844
845         /* alignment */
846         p = tcopy(a->n_left);
847         if (sz > SZINT/SZCHAR && r->n_type != UNIONTY && r->n_type != STRTY) {
848                 p = buildtree(PLUSpbcon(7));
849                 p = block(ANDpbcon(-8), p->n_typep->n_dfp->n_sue);
850         }
851
852         /* create a copy to a temp node */
853         q = tempnode(0p->n_typep->n_dfp->n_sue);
854         tmpnr = regno(q);
855         p = buildtree(ASSIGNqp);
856
857         q = tempnode(tmpnrp->n_typep->n_df,p->n_sue);
858         q = buildtree(PLUSqbcon(sz));
859         q = buildtree(ASSIGNa->n_leftq);
860
gmcgarry
1.7
861         q = buildtree(COMOPpq);
862
863         nfree(a->n_right);
864         nfree(a);
865         nfree(f); 
866
867         p = tempnode(tmpnrINCREF(r->n_type), r->n_dfr->n_sue);
868         p = buildtree(UMULpNIL);
869         p = buildtree(COMOPqp);
870
871         return p;
872
873 bad:
874         uerror("bad argument to __builtin_va_arg");
875         return bcon(0);
gmcgarry
1.6
876 }
877
878 NODE *
879 mips_builtin_va_end(NODE *fNODE *a)
880 {
gmcgarry
1.7
881         tfree(f);
882         tfree(a);
883         return bcon(0);
gmcgarry
1.6
884 }
885
886 NODE *
887 mips_builtin_va_copy(NODE *fNODE *a)
888 {
gmcgarry
1.7
889         if (a == NULL || a->n_op != CM || a->n_left->n_op == CM)
890                 goto bad;
891         tfree(f);
892         f = buildtree(ASSIGNa->n_lefta->n_right);
893         nfree(a);
gmcgarry
1.6
894         return f;
gmcgarry
1.7
895
896 bad:
897         uerror("bad argument to __buildtin_va_copy");
898         return bcon(0);
gmcgarry
1.6
899 }
gmcgarry
1.15
900
gmcgarry
1.17
901 static int constructor;
902 static int destructor;
903
ragge
1.13
904 /*
905  * Give target the opportunity of handling pragmas.
906  */
907 int
908 mypragma(char **ary)
909 {
gmcgarry
1.17
910         if (strcmp(ary[1], "tls") == 0) { 
911                 uerror("thread-local storage not supported for this target");
912                 return 1;
913         } 
914         if (strcmp(ary[1], "constructor") == 0 || strcmp(ary[1], "init") == 0) {
915                 constructor = 1;
916                 return 1;
917         }
918         if (strcmp(ary[1], "destructor") == 0 || strcmp(ary[1], "fini") == 0) {
919                 destructor = 1;
920                 return 1;
921         }
922
gmcgarry
1.15
923         return 0;
924 }
ragge
1.13
925
926 /*
927  * Called when a identifier has been declared, to give target last word.
928  */
929 void
930 fixdef(struct symtab *sp)
931 {
gmcgarry
1.17
932         if ((constructor || destructor) && (sp->sclass != PARAM)) {
933                 printf("\t.section .%ctors,\"aw\",@progbits\n",
934                     constructor ? 'c' : 'd');
935                 printf("\t.p2align 2\n");
936                 printf("\t.long %s\n"exname(sp->sname));
937                 constructor = destructor = 0;
938         }
939 }
940
941 void
942 pass1_lastchance(struct interpass *ip)
943 {
ragge
1.13
944 }
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-08-27 23:00 +0200