Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20110407185015

Diff

Diff from 1.25 to:

Annotations

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

Annotated File View

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