Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20110602154126

Diff

Diff from 1.26 to:

Annotations

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

Annotated File View

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