Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20110121214758

Diff

Diff from 1.24 to:

Annotations

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

Annotated File View

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