1 /* $Id: pftn.c,v 1.393 2014/10/11 10:53:14 ragge Exp $ */
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 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
28 *
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 *
33 * Redistributions of source code and documentation must retain the above
34 * copyright notice, this list of conditions and the following disclaimer.
35 * Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditionsand the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 * All advertising materials mentioning features or use of this software
39 * must display the following acknowledgement:
40 * This product includes software developed or owned by Caldera
41 * International, Inc.
42 * Neither the name of Caldera International, Inc. nor the names of other
43 * contributors may be used to endorse or promote products derived from
44 * this software without specific prior written permission.
45 *
46 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
47 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
48 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
49 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
50 * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
51 * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
55 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
56 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
57 * POSSIBILITY OF SUCH DAMAGE.
58 */
59
60 /*
61 * Many changes from the 32V sources, among them:
62 * - New symbol table manager (moved to another file).
63 * - Prototype saving/checks.
64 */
65
66 # include "pass1.h"
67 #include "unicode.h"
68
69 #include "cgram.h"
70
71 struct symtab *cftnsp;
72 int arglistcnt, dimfuncnt; /* statistics */
73 int symtabcnt, suedefcnt; /* statistics */
74 int autooff, /* the next unused automatic offset */
75 maxautooff, /* highest used automatic offset in function */
76 argoff; /* the next unused argument offset */
77 int retlab = NOLAB; /* return label for subroutine */
78 int brklab;
79 int contlab;
80 int flostat;
81 int blevel;
82 int reached, prolab;
83
84 struct params;
85
86 #define MKTY(p, t, d, s) r = talloc(); *r = *p; \
87 r = argcast(r, t, d, s); *p = *r; nfree(r);
88
89 /*
90 * Linked list stack while reading in structs.
91 */
92 struct rstack {
93 struct rstack *rnext;
94 int rsou;
95 int rstr;
96 struct symtab *rsym;
97 struct symtab *rb;
98 struct attr *ap;
99 int flags;
100 #define LASTELM 1
101 } *rpole;
102
103 /*
104 * Linked list for parameter (and struct elements) declaration.
105 */
106 static struct params {
107 struct params *prev;
108 struct symtab *sym;
109 } *lparam;
110 static int nparams;
111
112 /* defines used for getting things off of the initialization stack */
113
114 NODE *arrstk[10];
115 int arrstkp;
116 static int intcompare;
117 NODE *parlink;
118
119 void fixtype(NODE *p, int class);
120 int fixclass(int class, TWORD type);
121 static void dynalloc(struct symtab *p, int *poff);
122 static void evalidx(struct symtab *p);
123 int isdyn(struct symtab *p);
124 void inforce(OFFSZ n);
125 void vfdalign(int n);
126 static void ssave(struct symtab *);
127 #ifdef PCC_DEBUG
128 static void alprint(union arglist *al, int in);
129 #endif
130 static void lcommadd(struct symtab *sp);
131 static NODE *mkcmplx(NODE *p, TWORD dt);
132 static void cxargfixup(NODE *arg, TWORD dt, struct attr *ap);
133 extern int fun_inline;
134
135 void
defid(NODE * q,int class)136 defid(NODE *q, int class)
137 {
138 defid2(q, class, 0);
139 }
140
141 /*
142 * Declaration of an identifier. Handles redeclarations, hiding,
143 * incomplete types and forward declarations.
144 *
145 * q is a TYPE node setup after parsing with n_type, n_df and n_ap.
146 * n_sp is a pointer to the not-yet initalized symbol table entry
147 * unless it's a redeclaration or supposed to hide a variable.
148 */
149
150 void
defid2(NODE * q,int class,char * astr)151 defid2(NODE *q, int class, char *astr)
152 {
153 struct attr *ap;
154 struct symtab *p;
155 TWORD type, qual;
156 TWORD stp, stq;
157 int scl;
158 union dimfun *dsym, *ddef;
159 int slev, temp, changed;
160
161 if (q == NIL)
162 return; /* an error was detected */
163
164 #ifdef GCC_COMPAT
165 gcc_modefix(q);
166 #endif
167 p = q->n_sp;
168
169 if (p->sname == NULL)
170 cerror("defining null identifier");
171
172 #ifdef PCC_DEBUG
173 if (ddebug) {
174 printf("defid(%s '%s'(%p), ", p->sname, p->soname , p);
175 tprint(q->n_type, q->n_qual);
176 printf(", %s, (%p)), level %d\n\t", scnames(class),
177 q->n_df, blevel);
178 #ifdef GCC_COMPAT
179 dump_attr(q->n_ap);
180 #endif
181 }
182 #endif
183
184 fixtype(q, class);
185
186 type = q->n_type;
187 qual = q->n_qual;
188 class = fixclass(class, type);
189
190 stp = p->stype;
191 stq = p->squal;
192 slev = p->slevel;
193
194 #ifdef PCC_DEBUG
195 if (ddebug) {
196 printf(" modified to ");
197 tprint(type, qual);
198 printf(", %s\n", scnames(class));
199 printf(" previous def'n: ");
200 tprint(stp, stq);
201 printf(", %s, (%p,%p)), level %d\n",
202 scnames(p->sclass), p->sdf, p->sap, slev);
203 }
204 #endif
205
206 if (blevel == 1) {
207 switch (class) {
208 default:
209 if (!(class&FIELD) && !ISFTN(type))
210 uerror("declared argument %s missing",
211 p->sname );
212 break;
213 case MOS:
214 case MOU:
215 cerror("field5");
216 case TYPEDEF:
217 case PARAM:
218 break;
219 }
220 }
221
222 if (stp == UNDEF)
223 goto enter; /* New symbol */
224
225 if (type != stp)
226 goto mismatch;
227
228 if (blevel > slev && (class == AUTO || class == REGISTER))
229 /* new scope */
230 goto mismatch;
231
232 /*
233 * test (and possibly adjust) dimensions.
234 * also check that prototypes are correct.
235 */
236 dsym = p->sdf;
237 ddef = q->n_df;
238 changed = 0;
239 for (temp = type; temp & TMASK; temp = DECREF(temp)) {
240 if (ISARY(temp)) {
241 if (dsym->ddim == NOOFFSET) {
242 dsym->ddim = ddef->ddim;
243 changed = 1;
244 } else if (ddef->ddim != NOOFFSET &&
245 dsym->ddim!=ddef->ddim) {
246 goto mismatch;
247 }
248 ++dsym;
249 ++ddef;
250 } else if (ISFTN(temp)) {
251 /* add a late-defined prototype here */
252 if (!oldstyle && dsym->dfun == NULL)
253 dsym->dfun = ddef->dfun;
254 if (!oldstyle && ddef->dfun != NULL &&
255 chkftn(dsym->dfun, ddef->dfun))
256 uerror("declaration doesn't match prototype");
257 dsym++, ddef++;
258 }
259 }
260 #ifdef STABS
261 if (changed && gflag)
262 stabs_chgsym(p); /* symbol changed */
263 #endif
264
265 /* check that redeclarations are to the same structure */
266 if (temp == STRTY || temp == UNIONTY) {
267 if (strmemb(p->sap) != strmemb(q->n_ap))
268 goto mismatch;
269 }
270
271 scl = p->sclass;
272
273 #ifdef PCC_DEBUG
274 if (ddebug)
275 printf(" previous class: %s\n", scnames(scl));
276 #endif
277
278 /*
279 * Its allowed to add attributes to existing declarations.
280 * Be careful though not to trash existing attributes.
281 * XXX - code below is probably not correct.
282 */
283 if (p->sap && p->sap->atype <= ATTR_MAX) {
284 /* nothing special, just overwrite */
285 p->sap = q->n_ap;
286 } else {
287 if (p->slevel == blevel) {
288 for (ap = q->n_ap; ap; ap = ap->next) {
289 if (ap->atype > ATTR_MAX)
290 p->sap = attr_add(p->sap, attr_dup(ap, 3));
291 }
292 } else
293 p->sap = q->n_ap;
294 }
295
296 if (class & FIELD)
297 cerror("field1");
298 switch(class) {
299
300 case EXTERN:
301 if (astr)
302 p->soname = astr;
303 switch( scl ){
304 case STATIC:
305 case USTATIC:
306 if( slev==0 )
307 goto done;
308 break;
309 case EXTDEF:
310 case EXTERN:
311 goto done;
312 case SNULL:
313 if (p->sflags & SINLINE) {
314 p->sclass = EXTDEF;
315 inline_ref(p);
316 goto done;
317 }
318 break;
319 }
320 break;
321
322 case STATIC:
323 if (astr)
324 p->soname = astr;
325 if (scl==USTATIC || (scl==EXTERN && blevel==0)) {
326 p->sclass = STATIC;
327 goto done;
328 }
329 if (changed || (scl == STATIC && blevel == slev))
330 goto done; /* identical redeclaration */
331 break;
332
333 case USTATIC:
334 if (scl==STATIC || scl==USTATIC)
335 goto done;
336 break;
337
338 case TYPEDEF:
339 if (scl == class)
340 goto done;
341 break;
342
343 case MOU:
344 case MOS:
345 cerror("field6");
346
347 case EXTDEF:
348 switch (scl) {
349 case EXTERN:
350 p->sclass = EXTDEF;
351 goto done;
352 case USTATIC:
353 p->sclass = STATIC;
354 goto done;
355 case SNULL:
356 #ifdef GCC_COMPAT
357 /*
358 * Handle redeclarations of inlined functions.
359 * This is allowed if the previous declaration is of
360 * type gnu_inline.
361 */
362 if (attr_find(p->sap, GCC_ATYP_GNU_INLINE))
363 goto done;
364 #endif
365 break;
366 }
367 break;
368
369 case AUTO:
370 case REGISTER:
371 break; /* mismatch.. */
372 case SNULL:
373 if (fun_inline && ISFTN(type)) {
374 if (scl == EXTERN) {
375 p->sclass = EXTDEF;
376 inline_ref(p);
377 }
378 goto done;
379 }
380 break;
381 }
382
383 mismatch:
384
385 /*
386 * Only allowed for automatic variables.
387 */
388 if ((blevel == 2 && slev == 1) || blevel <= slev || class == EXTERN) {
389 uerror("redeclaration of %s", p->sname);
390 return;
391 }
392 q->n_sp = p = hide(p);
393
394 enter: /* make a new entry */
395
396 #ifdef PCC_DEBUG
397 if(ddebug)
398 printf(" new entry made\n");
399 #endif
400 p->stype = type;
401 p->squal = qual;
402 p->sclass = (char)class;
403 p->slevel = (char)blevel;
404 p->soffset = NOOFFSET;
405 if (q->n_ap)
406 p->sap = attr_add(q->n_ap, p->sap);
407
408 /* copy dimensions */
409 p->sdf = q->n_df;
410 /* Do not save param info for old-style functions */
411 if (ISFTN(type) && oldstyle)
412 p->sdf->dfun = NULL;
413
414 if (arrstkp)
415 evalidx(p);
416
417 /* allocate offsets */
418 if (class&FIELD) {
419 cerror("field2"); /* new entry */
420 } else switch (class) {
421
422 case REGISTER:
423 if (astr != NULL)
424 werror("no register assignment (yet)");
425 p->sclass = class = AUTO;
426 /* FALLTHROUGH */
427 case AUTO:
428 if (isdyn(p)) {
429 p->sflags |= SDYNARRAY;
430 dynalloc(p, &autooff);
431 } else
432 oalloc(p, &autooff);
433 break;
434
435 case PARAM:
436 if (q->n_type != FARG)
437 oalloc(p, &argoff);
438 break;
439
440 case STATIC:
441 case EXTDEF:
442 case EXTERN:
443 p->soffset = getlab();
444 /* FALLTHROUGH */
445 case USTATIC:
446 if (astr)
447 p->soname = astr;
448 break;
449
450 case MOU:
451 case MOS:
452 cerror("field7");
453 case SNULL:
454 #ifdef notdef
455 if (fun_inline) {
456 p->slevel = 1;
457 p->soffset = getlab();
458 }
459 #endif
460 break;
461 }
462
463 #ifdef STABS
464 if (gflag && p->stype != FARG)
465 stabs_newsym(p);
466 #endif
467
468 done:
469 fixdef(p); /* Leave last word to target */
470 #ifndef HAVE_WEAKREF
471 {
472 struct attr *at;
473
474 /* Refer renamed function */
475 if ((at = attr_find(p->sap, GCC_ATYP_WEAKREF)))
476 p->soname = at->sarg(0);
477 }
478 #endif
479 #ifdef PCC_DEBUG
480 if (ddebug) {
481 printf( " sdf, offset: %p, %d\n\t",
482 p->sdf, p->soffset);
483 #ifdef GCC_COMPAT
484 dump_attr(p->sap);
485 #endif
486 }
487 #endif
488 }
489
490 void
ssave(struct symtab * sym)491 ssave(struct symtab *sym)
492 {
493 struct params *p;
494
495 p = tmpalloc(sizeof(struct params));
496 p->prev = lparam;
497 p->sym = sym;
498 lparam = p;
499 }
500
501 /*
502 * end of function
503 */
504 void
ftnend(void)505 ftnend(void)
506 {
507 #ifdef GCC_COMPAT
508 struct attr *gc, *gd;
509 #endif
510 extern int *mkclabs(void);
511 extern NODE *cftnod;
512 extern struct savbc *savbc;
513 extern struct swdef *swpole;
514 extern int tvaloff;
515 char *c;
516
517 if (retlab != NOLAB && nerrors == 0) { /* inside a real function */
518 plabel(retlab);
519 if (cftnod)
520 ecomp(buildtree(FORCE, cftnod, NIL));
521 efcode(); /* struct return handled here */
522 if ((c = cftnsp->soname) == NULL)
523 c = addname(exname(cftnsp->sname));
524 SETOFF(maxautooff, ALCHAR);
525 send_passt(IP_EPILOG, maxautooff/SZCHAR, c,
526 cftnsp->stype, cftnsp->sclass == EXTDEF,
527 retlab, tvaloff, mkclabs());
528 }
529
530 cftnod = NIL;
531 tcheck();
532 brklab = contlab = retlab = NOLAB;
533 flostat = 0;
534 if (nerrors == 0) {
535 if (savbc != NULL)
536 cerror("bcsave error");
537 if (lparam != NULL)
538 cerror("parameter reset error");
539 if (swpole != NULL)
540 cerror("switch error");
541 }
542 #ifdef GCC_COMPAT
543 if (cftnsp) {
544 gc = attr_find(cftnsp->sap, GCC_ATYP_CONSTRUCTOR);
545 gd = attr_find(cftnsp->sap, GCC_ATYP_DESTRUCTOR);
546 if (gc || gd) {
547 struct symtab sts = *cftnsp;
548 NODE *p;
549 sts.stype = INCREF(sts.stype);
550 p = nametree(&sts);
551 p->n_op = ICON;
552 if (gc) {
553 locctr(CTORS, NULL);
554 inval(0, SZPOINT(0), p);
555 }
556 if (gd) {
557 locctr(DTORS, NULL);
558 inval(0, SZPOINT(0), p);
559 }
560 tfree(p);
561 }
562 }
563 #endif
564 savbc = NULL;
565 lparam = NULL;
566 cftnsp = NULL;
567 maxautooff = autooff = AUTOINIT;
568 reached = 1;
569
570 if (isinlining)
571 inline_end();
572 inline_prtout();
573
574 tmpfree(); /* Release memory resources */
575 }
576
577 static struct symtab nulsym = {
578 NULL, 0, 0, 0, 0, "null", "null", INT, 0, NULL, NULL
579 };
580
581 void
dclargs(void)582 dclargs(void)
583 {
584 union dimfun *df;
585 union arglist *al, *al2, *alb;
586 struct params *a;
587 struct symtab *p, **parr = NULL; /* XXX gcc */
588 int i;
589
590 /*
591 * Deal with fun(void) properly.
592 */
593 if (nparams == 1 && lparam->sym && lparam->sym->stype == VOID)
594 goto done;
595
596 /*
597 * Generate a list for bfcode().
598 * Parameters were pushed in reverse order.
599 */
600 if (nparams != 0)
601 parr = tmpalloc(sizeof(struct symtab *) * nparams);
602
603 if (nparams)
604 for (a = lparam, i = 0; a != NULL; a = a->prev) {
605 p = a->sym;
606 parr[i++] = p;
607 if (p == NULL) {
608 uerror("parameter %d name missing", i);
609 p = &nulsym; /* empty symtab */
610 }
611 if (p->stype == FARG)
612 p->stype = INT;
613 if (ISARY(p->stype)) {
614 p->stype += (PTR-ARY);
615 p->sdf++;
616 } else if (ISFTN(p->stype)) {
617 werror("function declared as argument");
618 p->stype = INCREF(p->stype);
619 }
620 #ifdef STABS
621 if (gflag)
622 stabs_newsym(p);
623 #endif
624 }
625 if (oldstyle && (df = cftnsp->sdf) && (al = df->dfun)) {
626 /*
627 * Check against prototype of oldstyle function.
628 */
629 alb = al2 = tmpalloc(sizeof(union arglist) * nparams * 3 + 1);
630 for (i = 0; i < nparams; i++) {
631 TWORD type = parr[i]->stype;
632 (al2++)->type = type;
633 if (ISSOU(BTYPE(type)))
634 (al2++)->sap = parr[i]->sap;
635 while (!ISFTN(type) && !ISARY(type) && type > BTMASK)
636 type = DECREF(type);
637 if (type > BTMASK)
638 (al2++)->df = parr[i]->sdf;
639 }
640 al2->type = TNULL;
641 intcompare = 1;
642 if (chkftn(al, alb))
643 uerror("function doesn't match prototype");
644 intcompare = 0;
645
646 }
647
648 if (oldstyle && nparams) {
649 /* Must recalculate offset for oldstyle args here */
650 argoff = ARGINIT;
651 for (i = 0; i < nparams; i++) {
652 parr[i]->soffset = NOOFFSET;
653 oalloc(parr[i], &argoff);
654 }
655 }
656
657 done: autooff = AUTOINIT;
658
659 plabel(prolab); /* after prolog, used in optimization */
660 retlab = getlab();
661 bfcode(parr, nparams);
662 if (fun_inline && (xinline
663 #ifdef GCC_COMPAT
664 || attr_find(cftnsp->sap, GCC_ATYP_ALW_INL)
665 #endif
666 ))
667 inline_args(parr, nparams);
668 plabel(getlab()); /* used when spilling */
669 if (parlink)
670 ecomp(parlink);
671 parlink = NIL;
672 lparam = NULL;
673 nparams = 0;
674 symclear(1); /* In case of function pointer args */
675 }
676
677 /*
678 * basic attributes for structs and enums
679 */
680 static struct attr *
seattr(void)681 seattr(void)
682 {
683 return attr_add(attr_new(ATTR_ALIGNED, 4), attr_new(ATTR_STRUCT, 2));
684 }
685
686 /*
687 * Struct/union/enum symtab construction.
688 */
689 static void
defstr(struct symtab * sp,int class)690 defstr(struct symtab *sp, int class)
691 {
692 sp->sclass = (char)class;
693 if (class == STNAME)
694 sp->stype = STRTY;
695 else if (class == UNAME)
696 sp->stype = UNIONTY;
697 else if (class == ENAME)
698 sp->stype = ENUMTY;
699 }
700
701 /*
702 * Declare a struct/union/enum tag.
703 * If not found, create a new tag with UNDEF type.
704 */
705 static struct symtab *
deftag(char * name,int class)706 deftag(char *name, int class)
707 {
708 struct symtab *sp;
709
710 if ((sp = lookup(name, STAGNAME))->sap == NULL) {
711 /* New tag */
712 defstr(sp, class);
713 } else if (sp->sclass != class)
714 uerror("tag %s redeclared", name);
715 return sp;
716 }
717
718 /*
719 * reference to a structure or union, with no definition
720 */
721 NODE *
rstruct(char * tag,int soru)722 rstruct(char *tag, int soru)
723 {
724 struct symtab *sp;
725
726 sp = deftag(tag, soru);
727 if (sp->sap == NULL)
728 sp->sap = seattr();
729 return mkty(sp->stype, 0, sp->sap);
730 }
731
732 static int enumlow, enumhigh;
733 int enummer;
734
735 /*
736 * Declare a member of enum.
737 */
738 void
moedef(char * name)739 moedef(char *name)
740 {
741 struct symtab *sp;
742
743 sp = lookup(name, SNORMAL);
744 if (sp->stype == UNDEF || (sp->slevel < blevel)) {
745 if (sp->stype != UNDEF)
746 sp = hide(sp);
747 sp->stype = INT; /* always */
748 sp->sclass = MOE;
749 sp->soffset = enummer;
750 } else
751 uerror("%s redeclared", name);
752 if (enummer < enumlow)
753 enumlow = enummer;
754 if (enummer > enumhigh)
755 enumhigh = enummer;
756 enummer++;
757 }
758
759 /*
760 * Declare an enum tag. Complain if already defined.
761 */
762 struct symtab *
enumhd(char * name)763 enumhd(char *name)
764 {
765 struct attr *ap;
766 struct symtab *sp;
767
768 enummer = enumlow = enumhigh = 0;
769 if (name == NULL)
770 return NULL;
771
772 sp = deftag(name, ENAME);
773 if (sp->stype != ENUMTY) {
774 if (sp->slevel == blevel)
775 uerror("%s redeclared", name);
776 sp = hide(sp);
777 defstr(sp, ENAME);
778 }
779 if (sp->sap == NULL)
780 ap = sp->sap = attr_new(ATTR_STRUCT, 4);
781 else
782 ap = attr_find(sp->sap, ATTR_STRUCT);
783 ap->amlist = sp;
784 return sp;
785 }
786
787 /*
788 * finish declaration of an enum
789 */
790 NODE *
enumdcl(struct symtab * sp)791 enumdcl(struct symtab *sp)
792 {
793 NODE *p;
794 TWORD t;
795
796 #ifdef ENUMSIZE
797 t = ENUMSIZE(enumhigh, enumlow);
798 #else
799 t = ctype(enumlow < 0 ? INT : UNSIGNED);
800 #ifdef notdef
801 if (enumhigh <= MAX_CHAR && enumlow >= MIN_CHAR)
802 t = ctype(CHAR);
803 else if (enumhigh <= MAX_SHORT && enumlow >= MIN_SHORT)
804 t = ctype(SHORT);
805 else
806 t = ctype(INT);
807 #endif
808 #endif
809
810 if (sp)
811 sp->stype = t;
812 p = mkty(t, 0, 0);
813 p->n_sp = sp;
814 return p;
815 }
816
817 /*
818 * Handle reference to an enum
819 */
820 NODE *
enumref(char * name)821 enumref(char *name)
822 {
823 struct symtab *sp;
824 NODE *p;
825
826 sp = lookup(name, STAGNAME);
827
828 #ifdef notdef
829 /*
830 * 6.7.2.3 Clause 2:
831 * "A type specifier of the form 'enum identifier' without an
832 * enumerator list shall only appear after the type it specifies
833 * is complete."
834 */
835 if (sp->sclass != ENAME)
836 uerror("enum %s undeclared", name);
837 #endif
838 if (sp->sclass == SNULL) {
839 /* declare existence of enum */
840 sp = enumhd(name);
841 sp->stype = ENUMTY;
842 }
843
844 p = mkty(sp->stype, 0, sp->sap);
845 p->n_sp = sp;
846 return p;
847 }
848
849 /*
850 * begining of structure or union declaration
851 * It's an error if this routine is called twice with the same struct.
852 */
853 struct rstack *
bstruct(char * name,int soru,NODE * gp)854 bstruct(char *name, int soru, NODE *gp)
855 {
856 struct rstack *r;
857 struct symtab *sp;
858 struct attr *ap, *gap;
859
860 #ifdef GCC_COMPAT
861 gap = gp ? gcc_attr_parse(gp) : NULL;
862 #else
863 gap = NULL;
864 #endif
865
866 if (name != NULL) {
867 sp = deftag(name, soru);
868 if (sp->sap == NULL)
869 sp->sap = seattr();
870 ap = attr_find(sp->sap, ATTR_ALIGNED);
871 if (ap->iarg(0) != 0) {
872 if (sp->slevel < blevel) {
873 sp = hide(sp);
874 defstr(sp, soru);
875 sp->sap = seattr();
876 } else
877 uerror("%s redeclared", name);
878 }
879 gap = sp->sap = attr_add(sp->sap, gap);
880 } else {
881 gap = attr_add(seattr(), gap);
882 sp = NULL;
883 }
884
885 r = tmpcalloc(sizeof(struct rstack));
886 r->rsou = soru;
887 r->rsym = sp;
888 r->rb = NULL;
889 r->ap = gap;
890 r->rnext = rpole;
891 rpole = r;
892
893 return r;
894 }
895
896 /*
897 * Called after a struct is declared to restore the environment.
898 * - If ALSTRUCT is defined, this will be the struct alignment and the
899 * struct size will be a multiple of ALSTRUCT, otherwise it will use
900 * the alignment of the largest struct member.
901 */
902 NODE *
dclstruct(struct rstack * r)903 dclstruct(struct rstack *r)
904 {
905 NODE *n;
906 struct attr *aps, *apb;
907 struct symtab *sp;
908 int al, sa, sz;
909
910 apb = attr_find(r->ap, ATTR_ALIGNED);
911 aps = attr_find(r->ap, ATTR_STRUCT);
912 aps->amlist = r->rb;
913
914 #ifdef ALSTRUCT
915 al = ALSTRUCT;
916 #else
917 al = ALCHAR;
918 #endif
919
920 /*
921 * extract size and alignment, calculate offsets
922 */
923 for (sp = r->rb; sp; sp = sp->snext) {
924 sa = talign(sp->stype, sp->sap);
925 if (sp->sclass & FIELD)
926 sz = sp->sclass&FLDSIZ;
927 else
928 sz = (int)tsize(sp->stype, sp->sdf, sp->sap);
929 if (sz > rpole->rstr)
930 rpole->rstr = sz; /* for use with unions */
931 /*
932 * set al, the alignment, to the lcm of the alignments
933 * of the members.
934 */
935 SETOFF(al, sa);
936 }
937
938 SETOFF(rpole->rstr, al);
939
940 aps->amsize = rpole->rstr;
941 apb->iarg(0) = al;
942
943 #ifdef PCC_DEBUG
944 if (ddebug) {
945 printf("dclstruct(%s): size=%d, align=%d\n",
946 r->rsym ? r->rsym->sname : "??",
947 aps->amsize, apb->iarg(0));
948 }
949 if (ddebug>1) {
950 printf("\tsize %d align %d link %p\n",
951 aps->amsize, apb->iarg(0), aps->amlist);
952 for (sp = aps->amlist; sp != NULL; sp = sp->snext) {
953 printf("\tmember %s(%p)\n", sp->sname, sp);
954 }
955 }
956 #endif
957
958 #ifdef STABS
959 if (gflag)
960 stabs_struct(r->rsym, r->ap);
961 #endif
962
963 rpole = r->rnext;
964 n = mkty(r->rsou == STNAME ? STRTY : UNIONTY, 0, r->ap);
965 n->n_sp = r->rsym;
966
967 n->n_qual |= 1; /* definition place XXX used by attributes */
968 return n;
969 }
970
971 /*
972 * Add a new member to the current struct or union being declared.
973 */
974 void
soumemb(NODE * n,char * name,int class)975 soumemb(NODE *n, char *name, int class)
976 {
977 struct symtab *sp, *lsp;
978 int incomp, tsz, al;
979 TWORD t;
980
981 if (rpole == NULL)
982 cerror("soumemb");
983
984 /* check if tag name exists */
985 lsp = NULL;
986 for (sp = rpole->rb; sp != NULL; lsp = sp, sp = sp->snext)
987 if (*name != '*' && sp->sname == name)
988 uerror("redeclaration of %s", name);
989
990 sp = getsymtab(name, SMOSNAME);
991 if (rpole->rb == NULL)
992 rpole->rb = sp;
993 else
994 lsp->snext = sp;
995
996 n->n_sp = sp;
997 sp->stype = n->n_type;
998 sp->squal = n->n_qual;
999 sp->slevel = blevel;
1000 sp->sap = n->n_ap;
1001 sp->sdf = n->n_df;
1002
1003 if (class & FIELD) {
1004 sp->sclass = (char)class;
1005 if (rpole->rsou == UNAME)
1006 rpole->rstr = 0;
1007 falloc(sp, class&FLDSIZ, NIL);
1008 } else if (rpole->rsou == STNAME || rpole->rsou == UNAME) {
1009 sp->sclass = rpole->rsou == STNAME ? MOS : MOU;
1010 if (sp->sclass == MOU)
1011 rpole->rstr = 0;
1012 al = talign(sp->stype, sp->sap);
1013 tsz = (int)tsize(sp->stype, sp->sdf, sp->sap);
1014 sp->soffset = upoff(tsz, al, &rpole->rstr);
1015 }
1016
1017 /*
1018 * 6.7.2.1 clause 16:
1019 * "...the last member of a structure with more than one
1020 * named member may have incomplete array type;"
1021 */
1022 if (ISARY(sp->stype) && sp->sdf->ddim == NOOFFSET)
1023 incomp = 1;
1024 else
1025 incomp = 0;
1026 if ((rpole->flags & LASTELM) || (rpole->rb == sp && incomp == 1))
1027 uerror("incomplete array in struct");
1028 if (incomp == 1)
1029 rpole->flags |= LASTELM;
1030
1031 /*
1032 * 6.7.2.1 clause 2:
1033 * "...such a structure shall not be a member of a structure
1034 * or an element of an array."
1035 */
1036 t = sp->stype;
1037 if (rpole->rsou != STNAME || BTYPE(t) != STRTY)
1038 return; /* not for unions */
1039 while (ISARY(t))
1040 t = DECREF(t);
1041 if (ISPTR(t))
1042 return;
1043
1044 if ((lsp = strmemb(sp->sap)) != NULL) {
1045 for (; lsp->snext; lsp = lsp->snext)
1046 ;
1047 if (ISARY(lsp->stype) && lsp->snext &&
1048 lsp->sdf->ddim == NOOFFSET)
1049 uerror("incomplete struct in struct");
1050 }
1051 }
1052
1053 /*
1054 * error printing routine in parser
1055 */
1056 void
yyerror(char * s)1057 yyerror(char *s)
1058 {
1059 uerror(s);
1060 }
1061
1062 void yyaccpt(void);
1063 void
yyaccpt(void)1064 yyaccpt(void)
1065 {
1066 ftnend();
1067 }
1068
1069 /*
1070 * p is top of type list given to tymerge later.
1071 * Find correct CALL node and declare parameters from there.
1072 */
1073 void
ftnarg(NODE * p)1074 ftnarg(NODE *p)
1075 {
1076 NODE *q;
1077
1078 #ifdef PCC_DEBUG
1079 if (ddebug > 2)
1080 printf("ftnarg(%p)\n", p);
1081 #endif
1082 /*
1083 * Push argument symtab entries onto param stack in reverse order,
1084 * due to the nature of the stack it will be reclaimed correct.
1085 */
1086 for (; p->n_op != NAME; p = p->n_left) {
1087 if (p->n_op == UCALL && p->n_left->n_op == NAME)
1088 return; /* Nothing to enter */
1089 if (p->n_op == CALL && p->n_left->n_op == NAME)
1090 break;
1091 }
1092
1093 p = p->n_right;
1094 while (p->n_op == CM) {
1095 q = p->n_right;
1096 if (q->n_op != ELLIPSIS) {
1097 ssave(q->n_sp);
1098 nparams++;
1099 #ifdef PCC_DEBUG
1100 if (ddebug > 2)
1101 printf(" saving sym %s (%p) from (%p)\n",
1102 q->n_sp->sname, q->n_sp, q);
1103 #endif
1104 }
1105 p = p->n_left;
1106 }
1107 ssave(p->n_sp);
1108 if (p->n_type != VOID)
1109 nparams++;
1110
1111 #ifdef PCC_DEBUG
1112 if (ddebug > 2)
1113 printf(" saving sym %s (%p) from (%p)\n",
1114 nparams ? p->n_sp->sname : "<noname>", p->n_sp, p);
1115 #endif
1116 }
1117
1118 /*
1119 * compute the alignment of an object with type ty, sizeoff index s
1120 */
1121 int
talign(unsigned int ty,struct attr * apl)1122 talign(unsigned int ty, struct attr *apl)
1123 {
1124 struct attr *al;
1125 int a;
1126
1127 for (; ty > BTMASK; ty = DECREF(ty)) {
1128 switch (ty & TMASK) {
1129 case PTR:
1130 return(ALPOINT);
1131 case ARY:
1132 continue;
1133 case FTN:
1134 cerror("compiler takes alignment of function");
1135 }
1136 }
1137
1138 /* check for alignment attribute */
1139 if ((al = attr_find(apl, ATTR_ALIGNED))) {
1140 if ((a = al->iarg(0)) == 0) {
1141 uerror("no alignment");
1142 a = ALINT;
1143 }
1144 return a;
1145 }
1146
1147 #ifndef NO_COMPLEX
1148 if (ISITY(ty))
1149 ty -= (FIMAG-FLOAT);
1150 #endif
1151 ty = BTYPE(ty);
1152 if (ty >= CHAR && ty <= ULONGLONG && ISUNSIGNED(ty))
1153 ty = DEUNSIGN(ty);
1154
1155 switch (ty) {
1156 #ifdef GCC_COMPAT
1157 case VOID: a = ALCHAR; break; /* GCC */
1158 #endif
1159 case BOOL: a = ALBOOL; break;
1160 case CHAR: a = ALCHAR; break;
1161 case SHORT: a = ALSHORT; break;
1162 case INT: a = ALINT; break;
1163 case LONG: a = ALLONG; break;
1164 case LONGLONG: a = ALLONGLONG; break;
1165 case FLOAT: a = ALFLOAT; break;
1166 case DOUBLE: a = ALDOUBLE; break;
1167 case LDOUBLE: a = ALLDOUBLE; break;
1168 default:
1169 uerror("no alignment");
1170 a = ALINT;
1171 }
1172 return a;
1173 }
1174
1175 short sztable[] = { 0, SZBOOL, SZCHAR, SZCHAR, SZSHORT, SZSHORT, SZINT, SZINT,
1176 SZLONG, SZLONG, SZLONGLONG, SZLONGLONG, SZFLOAT, SZDOUBLE, SZLDOUBLE };
1177
1178 /* compute the size associated with type ty,
1179 * dimoff d, and sizoff s */
1180 /* BETTER NOT BE CALLED WHEN t, d, and s REFER TO A BIT FIELD... */
1181 OFFSZ
tsize(TWORD ty,union dimfun * d,struct attr * apl)1182 tsize(TWORD ty, union dimfun *d, struct attr *apl)
1183 {
1184 struct attr *ap, *ap2;
1185 OFFSZ mult, sz;
1186
1187 mult = 1;
1188
1189 for (; ty > BTMASK; ty = DECREF(ty)) {
1190 switch (ty & TMASK) {
1191
1192 case FTN:
1193 uerror( "cannot take size of function");
1194 case PTR:
1195 return( SZPOINT(ty) * mult );
1196 case ARY:
1197 if (d->ddim == NOOFFSET)
1198 return 0;
1199 if (d->ddim < 0)
1200 cerror("tsize: dynarray");
1201 mult *= d->ddim;
1202 d++;
1203 }
1204 }
1205
1206 #ifndef NO_COMPLEX
1207 if (ISITY(ty))
1208 ty -= (FIMAG-FLOAT);
1209 #endif
1210
1211 if (ty == VOID)
1212 ty = CHAR;
1213 if (ty <= LDOUBLE)
1214 sz = sztable[ty];
1215 else if (ISSOU(ty)) {
1216 if ((ap = strattr(apl)) == NULL ||
1217 (ap2 = attr_find(apl, ATTR_ALIGNED)) == NULL ||
1218 (ap2->iarg(0) == 0)) {
1219 uerror("unknown structure/union/enum");
1220 sz = SZINT;
1221 } else
1222 sz = ap->amsize;
1223 } else {
1224 uerror("unknown type");
1225 sz = SZINT;
1226 }
1227
1228 return((unsigned int)sz * mult);
1229 }
1230
1231 /*
1232 * Save string (and print it out). If wide then wide string.
1233 */
1234 NODE *
strend(int wide,char * str)1235 strend(int wide, char *str)
1236 {
1237 struct symtab *sp;
1238 NODE *p;
1239
1240 /* If an identical string is already emitted, just forget this one */
1241 if (wide) {
1242 /* Do not save wide strings, at least not now */
1243 sp = getsymtab(str, SSTRING|STEMP);
1244 } else {
1245 str = addstring(str); /* enter string in string table */
1246 sp = lookup(str, SSTRING); /* check for existence */
1247 }
1248
1249 if (sp->soffset == 0) { /* No string */
1250 char *wr;
1251 int i;
1252
1253 sp->sclass = STATIC;
1254 sp->slevel = 1;
1255 sp->soffset = getlab();
1256 sp->squal = (CON >> TSHIFT);
1257 sp->sdf = permalloc(sizeof(union dimfun));
1258 if (wide) {
1259 sp->stype = WCHAR_TYPE+ARY;
1260 } else {
1261 if (xuchar) {
1262 sp->stype = UCHAR+ARY;
1263 } else {
1264 sp->stype = CHAR+ARY;
1265 }
1266 }
1267 for (wr = sp->sname, i = 1; *wr; i++) {
1268 if (wide)
1269 (void)u82cp(&wr);
1270 else if (*wr == '\\')
1271 (void)esccon(&wr);
1272 else
1273 wr++;
1274 }
1275 sp->sdf->ddim = i;
1276
1277 if (wide)
1278 inwstring(sp);
1279 else
1280 instring(sp);
1281 }
1282
1283 p = block(NAME, NIL, NIL, sp->stype, sp->sdf, sp->sap);
1284 p->n_sp = sp;
1285 return(clocal(p));
1286 }
1287
1288 /*
1289 * Print out a wide string by calling ninval().
1290 */
1291 void
inwstring(struct symtab * sp)1292 inwstring(struct symtab *sp)
1293 {
1294 char *s = sp->sname;
1295 NODE *p;
1296 int n;
1297
1298 locctr(STRNG, sp);
1299 defloc(sp);
1300 p = xbcon(0, NULL, WCHAR_TYPE);
1301 for (n = sp->sdf->ddim; n > 0; n--) {
1302 p->n_lval = u82cp(&s);
1303 inval(0, tsize(WCHAR_TYPE, NULL, NULL), p);
1304 }
1305 nfree(p);
1306 }
1307
1308 #ifndef MYINSTRING
1309 /*
1310 * Print out a string of characters.
1311 * Assume that the assembler understands C-style escape
1312 * sequences.
1313 */
1314 void
instring(struct symtab * sp)1315 instring(struct symtab *sp)
1316 {
1317 char *s, *str;
1318
1319 locctr(STRNG, sp);
1320 defloc(sp);
1321
1322 printf("\t.ascii \"");
1323 str = s = sp->sname;
1324 while (*s) {
1325 if (*s == '\\')
1326 (void)esccon(&s);
1327 else
1328 s++;
1329
1330 if (s - str > 60) {
1331 fwrite(str, 1, s - str, stdout);
1332 printf("\"\n\t.ascii \"");
1333 str = s;
1334 }
1335 }
1336
1337 fwrite(str, 1, s - str, stdout);
1338 printf("\\0\"\n");
1339 }
1340 #endif
1341
1342 /*
1343 * update the offset pointed to by poff; return the
1344 * offset of a value of size `size', alignment `alignment',
1345 * given that off is increasing
1346 */
1347 int
upoff(int size,int alignment,int * poff)1348 upoff(int size, int alignment, int *poff)
1349 {
1350 int off;
1351
1352 off = *poff;
1353 SETOFF(off, alignment);
1354 if (off < 0)
1355 cerror("structure or stack overgrown"); /* wrapped */
1356 *poff = off+size;
1357 return (off);
1358 }
1359
1360 /*
1361 * allocate p with offset *poff, and update *poff
1362 */
1363 int
oalloc(struct symtab * p,int * poff)1364 oalloc(struct symtab *p, int *poff )
1365 {
1366 int al, off, tsz;
1367 int noff;
1368
1369 /*
1370 * Only generate tempnodes if we are optimizing,
1371 * and only for integers, floats or pointers,
1372 * and not if the type on this level is volatile.
1373 */
1374 if (xtemps && ((p->sclass == AUTO) || (p->sclass == REGISTER)) &&
1375 (p->stype < STRTY || ISPTR(p->stype)) &&
1376 !(cqual(p->stype, p->squal) & VOL) && cisreg(p->stype)) {
1377 NODE *tn = tempnode(0, p->stype, p->sdf, p->sap);
1378 p->soffset = regno(tn);
1379 p->sflags |= STNODE;
1380 nfree(tn);
1381 return 0;
1382 }
1383
1384 al = talign(p->stype, p->sap);
1385 noff = off = *poff;
1386 tsz = (int)tsize(p->stype, p->sdf, p->sap);
1387 #ifdef BACKAUTO
1388 if (p->sclass == AUTO) {
1389 noff = off + tsz;
1390 if (noff < 0)
1391 cerror("stack overflow");
1392 SETOFF(noff, al);
1393 off = -noff;
1394 } else
1395 #endif
1396 if (p->sclass == PARAM && (p->stype == CHAR || p->stype == UCHAR ||
1397 p->stype == SHORT || p->stype == USHORT || p->stype == BOOL)) {
1398 off = upoff(SZINT, ALINT, &noff);
1399 #if TARGET_ENDIAN == TARGET_BE
1400 off = noff - tsz;
1401 #endif
1402 } else {
1403 off = upoff(tsz, al, &noff);
1404 }
1405
1406 if (p->sclass != REGISTER) {
1407 /* in case we are allocating stack space for register arguments */
1408 if (p->soffset == NOOFFSET)
1409 p->soffset = off;
1410 else if(off != p->soffset)
1411 return(1);
1412 }
1413
1414 *poff = noff;
1415 return(0);
1416 }
1417
1418 /*
1419 * Delay emission of code generated in argument headers.
1420 */
1421 static void
edelay(NODE * p)1422 edelay(NODE *p)
1423 {
1424 if (blevel == 1) {
1425 /* Delay until after declarations */
1426 if (parlink == NULL)
1427 parlink = p;
1428 else
1429 parlink = block(COMOP, parlink, p, 0, 0, 0);
1430 } else
1431 ecomp(p);
1432 }
1433
1434 /*
1435 * Traverse through the array args, evaluate them and put the
1436 * resulting temp numbers in the dim fields.
1437 */
1438 static void
evalidx(struct symtab * sp)1439 evalidx(struct symtab *sp)
1440 {
1441 union dimfun *df;
1442 NODE *p;
1443 TWORD t;
1444 int astkp = 0;
1445
1446 if (arrstk[0] == NIL)
1447 astkp++; /* for parameter arrays */
1448
1449 if (isdyn(sp))
1450 sp->sflags |= SDYNARRAY;
1451
1452 df = sp->sdf;
1453 for (t = sp->stype; t > BTMASK; t = DECREF(t)) {
1454 if (!ISARY(t))
1455 continue;
1456 if (df->ddim == -1) {
1457 p = tempnode(0, INT, 0, 0);
1458 df->ddim = -regno(p);
1459 edelay(buildtree(ASSIGN, p, arrstk[astkp++]));
1460 }
1461 df++;
1462 }
1463 arrstkp = 0;
1464 }
1465
1466 /*
1467 * Return 1 if dynamic array, 0 otherwise.
1468 */
1469 int
isdyn(struct symtab * sp)1470 isdyn(struct symtab *sp)
1471 {
1472 union dimfun *df = sp->sdf;
1473 TWORD t;
1474
1475 for (t = sp->stype; t > BTMASK; t = DECREF(t)) {
1476 if (!ISARY(t))
1477 return 0;
1478 if (df->ddim < 0 && df->ddim != NOOFFSET)
1479 return 1;
1480 df++;
1481 }
1482 return 0;
1483 }
1484
1485 /*
1486 * Allocate space on the stack for dynamic arrays (or at least keep track
1487 * of the index).
1488 * Strategy is as follows:
1489 * - first entry is a pointer to the dynamic datatype.
1490 * - if it's a one-dimensional array this will be the only entry used.
1491 * - if it's a multi-dimensional array the following (numdim-1) integers
1492 * will contain the sizes to multiply the indexes with.
1493 * - code to write the dimension sizes this will be generated here.
1494 * - code to allocate space on the stack will be generated here.
1495 */
1496 static void
dynalloc(struct symtab * p,int * poff)1497 dynalloc(struct symtab *p, int *poff)
1498 {
1499 union dimfun *df;
1500 NODE *n, *tn, *pol;
1501 TWORD t;
1502
1503 /*
1504 * The pointer to the array is not necessarily stored in a
1505 * TEMP node, but if it is, its number is in the soffset field;
1506 */
1507 t = p->stype;
1508 p->sflags |= STNODE;
1509 p->stype = INCREF(p->stype); /* Make this an indirect pointer */
1510 tn = tempnode(0, p->stype, p->sdf, p->sap);
1511 p->soffset = regno(tn);
1512
1513 df = p->sdf;
1514
1515 pol = bcon(1);
1516 for (; t > BTMASK; t = DECREF(t)) {
1517 if (!ISARY(t))
1518 break;
1519 if (df->ddim < 0)
1520 n = tempnode(-df->ddim, INT, 0, 0);
1521 else
1522 n = bcon(df->ddim);
1523
1524 pol = buildtree(MUL, pol, n);
1525 df++;
1526 }
1527 /* Create stack gap */
1528 spalloc(tn, pol, tsize(t, 0, p->sap));
1529 }
1530
1531 /*
1532 * allocate a field of width w
1533 * new is 0 if new entry, 1 if redefinition, -1 if alignment
1534 */
1535 int
falloc(struct symtab * p,int w,NODE * pty)1536 falloc(struct symtab *p, int w, NODE *pty)
1537 {
1538 TWORD otype, type;
1539 int al,sz;
1540
1541 otype = type = p ? p->stype : pty->n_type;
1542
1543 if (type == BOOL)
1544 type = BOOL_TYPE;
1545 if (!ISINTEGER(type)) {
1546 uerror("illegal field type");
1547 type = INT;
1548 }
1549
1550 al = talign(type, NULL);
1551 sz = tsize(type, NULL, NULL);
1552
1553 if (w > sz) {
1554 uerror("field too big");
1555 w = sz;
1556 }
1557
1558 if (w == 0) { /* align only */
1559 SETOFF(rpole->rstr, al);
1560 if (p != NULL)
1561 uerror("zero size field");
1562 return(0);
1563 }
1564
1565 if (rpole->rstr%al + w > sz)
1566 SETOFF(rpole->rstr, al);
1567 if (p == NULL) {
1568 rpole->rstr += w; /* we know it will fit */
1569 return(0);
1570 }
1571
1572 /* establish the field */
1573
1574 p->soffset = rpole->rstr;
1575 rpole->rstr += w;
1576 p->stype = otype;
1577 fldty(p);
1578 return(0);
1579 }
1580
1581 /*
1582 * Check if this symbol should be a common or must be handled in data seg.
1583 */
1584 static void
commchk(struct symtab * sp)1585 commchk(struct symtab *sp)
1586 {
1587 if ((sp->sflags & STLS)
1588 #ifdef GCC_COMPAT
1589 || attr_find(sp->sap, GCC_ATYP_SECTION)
1590 #endif
1591 ) {
1592 /* TLS handled in data segment */
1593 if (sp->sclass == EXTERN)
1594 sp->sclass = EXTDEF;
1595 beginit(sp);
1596 endinit(1);
1597 } else {
1598 symdirec(sp);
1599 defzero(sp);
1600 }
1601 }
1602
1603 void
nidcl(NODE * p,int class)1604 nidcl(NODE *p, int class)
1605 {
1606 nidcl2(p, class, 0);
1607 }
1608
1609 /*
1610 * handle unitialized declarations assumed to be not functions:
1611 * int a;
1612 * extern int a;
1613 * static int a;
1614 */
1615 void
nidcl2(NODE * p,int class,char * astr)1616 nidcl2(NODE *p, int class, char *astr)
1617 {
1618 struct symtab *sp;
1619 int commflag = 0;
1620
1621 /* compute class */
1622 if (class == SNULL) {
1623 if (blevel > 1)
1624 class = AUTO;
1625 else if (blevel != 0 || rpole)
1626 cerror( "nidcl error" );
1627 else /* blevel = 0 */
1628 commflag = 1, class = EXTERN;
1629 }
1630
1631 defid2(p, class, astr);
1632
1633 sp = p->n_sp;
1634 /* check if forward decl */
1635 if (ISARY(sp->stype) && sp->sdf->ddim == NOOFFSET)
1636 return;
1637
1638 if (sp->sflags & SASG)
1639 return; /* already initialized */
1640
1641 switch (class) {
1642 case EXTDEF:
1643 /* simulate initialization by 0 */
1644 simpleinit(p->n_sp, bcon(0));
1645 break;
1646 case EXTERN:
1647 if (commflag)
1648 lcommadd(p->n_sp);
1649 else
1650 extdec(p->n_sp);
1651 break;
1652 case STATIC:
1653 if (blevel == 0)
1654 lcommadd(p->n_sp);
1655 else
1656 commchk(p->n_sp);
1657 break;
1658 }
1659 }
1660
1661 struct lcd {
1662 SLIST_ENTRY(lcd) next;
1663 struct symtab *sp;
1664 };
1665
1666 static SLIST_HEAD(, lcd) lhead = { NULL, &lhead.q_forw};
1667
1668 /*
1669 * Add a local common statement to the printout list.
1670 */
1671 void
lcommadd(struct symtab * sp)1672 lcommadd(struct symtab *sp)
1673 {
1674 struct lcd *lc, *lcp;
1675
1676 lcp = NULL;
1677 SLIST_FOREACH(lc, &lhead, next) {
1678 if (lc->sp == sp)
1679 return; /* already exists */
1680 if (lc->sp == NULL && lcp == NULL)
1681 lcp = lc;
1682 }
1683 if (lcp == NULL) {
1684 lc = permalloc(sizeof(struct lcd));
1685 lc->sp = sp;
1686 SLIST_INSERT_LAST(&lhead, lc, next);
1687 } else
1688 lcp->sp = sp;
1689 }
1690
1691 /*
1692 * Delete a local common statement.
1693 */
1694 void
lcommdel(struct symtab * sp)1695 lcommdel(struct symtab *sp)
1696 {
1697 struct lcd *lc;
1698
1699 SLIST_FOREACH(lc, &lhead, next) {
1700 if (lc->sp == sp) {
1701 lc->sp = NULL;
1702 return;
1703 }
1704 }
1705 }
1706
1707 /*
1708 * Print out the remaining common statements.
1709 */
1710 void
lcommprint(void)1711 lcommprint(void)
1712 {
1713 struct lcd *lc;
1714
1715 SLIST_FOREACH(lc, &lhead, next) {
1716 if (lc->sp != NULL)
1717 commchk(lc->sp);
1718 }
1719 }
1720
1721 /*
1722 * Merge given types to a single node.
1723 * Any type can end up here.
1724 * p is the old node, q is the old (if any).
1725 * CLASS is AUTO, EXTERN, REGISTER, STATIC or TYPEDEF.
1726 * QUALIFIER is VOL or CON
1727 * TYPE is CHAR, SHORT, INT, LONG, SIGNED, UNSIGNED, VOID, BOOL, FLOAT,
1728 * DOUBLE, STRTY, UNIONTY.
1729 */
1730 struct typctx {
1731 int class, qual, sig, uns, cmplx, imag, err;
1732 TWORD type;
1733 NODE *saved;
1734 struct attr *pre, *post;
1735 };
1736
1737 static void
typwalk(NODE * p,void * arg)1738 typwalk(NODE *p, void *arg)
1739 {
1740 struct typctx *tc = arg;
1741
1742 #define cmop(x,y) block(CM, x, y, INT, 0, 0)
1743 switch (p->n_op) {
1744 case ATTRIB:
1745 #ifdef GCC_COMPAT
1746 if (tc->saved && (tc->saved->n_qual & 1)) {
1747 tc->post = attr_add(tc->post,gcc_attr_parse(p->n_left));
1748 } else {
1749 tc->pre = attr_add(tc->pre, gcc_attr_parse(p->n_left));
1750 }
1751 p->n_left = bcon(0); /* For tfree() */
1752 #else
1753 uerror("gcc type attribute used");
1754 #endif
1755 break;
1756 case CLASS:
1757 if (p->n_type == 0)
1758 break; /* inline hack */
1759 if (tc->class)
1760 tc->err = 1; /* max 1 class */
1761 tc->class = p->n_type;
1762 break;
1763
1764 case QUALIFIER:
1765 if (p->n_qual == 0 &&
1766 ((tc->saved && !ISPTR(tc->saved->n_type)) ||
1767 (tc->saved == 0)))
1768 uerror("invalid use of 'restrict'");
1769 tc->qual |= p->n_qual >> TSHIFT;
1770 break;
1771
1772 case TYPE:
1773 if (p->n_sp != NULL || ISSOU(p->n_type)) {
1774 /* typedef, enum or struct/union */
1775 if (tc->saved || tc->type)
1776 tc->err = 1;
1777 #ifdef GCC_COMPAT
1778 if (ISSOU(p->n_type) && p->n_left) {
1779 if (tc->post)
1780 cerror("typwalk");
1781 tc->post = gcc_attr_parse(p->n_left);
1782 }
1783 #endif
1784 tc->saved = ccopy(p);
1785 break;
1786 }
1787
1788 switch (p->n_type) {
1789 case BOOL:
1790 case CHAR:
1791 case FLOAT:
1792 case VOID:
1793 if (tc->type)
1794 tc->err = 1;
1795 tc->type = p->n_type;
1796 break;
1797 case DOUBLE:
1798 if (tc->type == 0)
1799 tc->type = DOUBLE;
1800 else if (tc->type == LONG)
1801 tc->type = LDOUBLE;
1802 else
1803 tc->err = 1;
1804 break;
1805 case SHORT:
1806 if (tc->type == 0 || tc->type == INT)
1807 tc->type = SHORT;
1808 else
1809 tc->err = 1;
1810 break;
1811 case INT:
1812 if (tc->type == SHORT || tc->type == LONG ||
1813 tc->type == LONGLONG)
1814 break;
1815 else if (tc->type == 0)
1816 tc->type = INT;
1817 else
1818 tc->err = 1;
1819 break;
1820 case LONG:
1821 if (tc->type == 0)
1822 tc->type = LONG;
1823 else if (tc->type == INT)
1824 break;
1825 else if (tc->type == LONG)
1826 tc->type = LONGLONG;
1827 else if (tc->type == DOUBLE)
1828 tc->type = LDOUBLE;
1829 else
1830 tc->err = 1;
1831 break;
1832 case SIGNED:
1833 if (tc->sig || tc->uns)
1834 tc->err = 1;
1835 tc->sig = 1;
1836 break;
1837 case UNSIGNED:
1838 if (tc->sig || tc->uns)
1839 tc->err = 1;
1840 tc->uns = 1;
1841 break;
1842 case COMPLEX:
1843 tc->cmplx = 1;
1844 break;
1845 case IMAG:
1846 tc->imag = 1;
1847 break;
1848 default:
1849 cerror("typwalk");
1850 }
1851 }
1852
1853 }
1854
1855 NODE *
typenode(NODE * p)1856 typenode(NODE *p)
1857 {
1858 struct symtab *sp;
1859 struct typctx tc;
1860 NODE *q;
1861 char *c;
1862
1863 memset(&tc, 0, sizeof(struct typctx));
1864
1865 flist(p, typwalk, &tc);
1866 tfree(p);
1867
1868 if (tc.err)
1869 goto bad;
1870
1871 if (tc.cmplx || tc.imag) {
1872 if (tc.type == 0)
1873 tc.type = DOUBLE;
1874 if ((tc.cmplx && tc.imag) || tc.sig || tc.uns ||
1875 !ISFTY(tc.type))
1876 goto bad;
1877 if (tc.cmplx) {
1878 c = tc.type == DOUBLE ? "0d" :
1879 tc.type == FLOAT ? "0f" : "0l";
1880 sp = lookup(addname(c), 0);
1881 tc.type = STRTY;
1882 tc.saved = mkty(tc.type, sp->sdf, sp->sap);
1883 tc.saved->n_sp = sp;
1884 tc.type = 0;
1885 } else
1886 tc.type += (FIMAG-FLOAT);
1887 }
1888
1889 if (tc.saved && tc.type)
1890 goto bad;
1891 if (tc.sig || tc.uns) {
1892 if (tc.type == 0)
1893 tc.type = tc.sig ? INT : UNSIGNED;
1894 if (tc.type > ULONGLONG)
1895 goto bad;
1896 if (tc.uns)
1897 tc.type = ENUNSIGN(tc.type);
1898 }
1899
1900 if (xuchar && tc.type == CHAR && tc.sig == 0)
1901 tc.type = UCHAR;
1902
1903 #ifdef GCC_COMPAT
1904 if (pragma_packed) {
1905 q = bdty(CALL, bdty(NAME, "packed"), bcon(pragma_packed));
1906 tc.post = attr_add(tc.post, gcc_attr_parse(q));
1907 }
1908 if (pragma_aligned) {
1909 /* Deal with relevant pragmas */
1910 q = bdty(CALL, bdty(NAME, "aligned"), bcon(pragma_aligned));
1911 tc.post = attr_add(tc.post, gcc_attr_parse(q));
1912 }
1913 pragma_aligned = pragma_packed = 0;
1914 #endif
1915 if ((q = tc.saved) == NULL) {
1916 TWORD t;
1917 if ((t = BTYPE(tc.type)) > LDOUBLE && t != VOID &&
1918 t != BOOL && !(t >= FIMAG && t <= LIMAG))
1919 cerror("typenode2 t %x", tc.type);
1920 if (t == UNDEF) {
1921 t = INT;
1922 MODTYPE(tc.type, INT);
1923 }
1924 q = mkty(tc.type, 0, 0);
1925 }
1926 q->n_ap = attr_add(q->n_ap, tc.post);
1927 q->n_qual = tc.qual;
1928 q->n_lval = tc.class;
1929 #ifdef GCC_COMPAT
1930 if (tc.post) {
1931 /* Can only occur for TYPEDEF, STRUCT or UNION */
1932 if (tc.saved == NULL)
1933 cerror("typenode");
1934 if (tc.saved->n_sp) /* trailer attributes for structs */
1935 tc.saved->n_sp->sap = q->n_ap;
1936 }
1937 if (tc.pre)
1938 q->n_ap = attr_add(q->n_ap, tc.pre);
1939 gcc_tcattrfix(q);
1940 #endif
1941 return q;
1942
1943 bad: uerror("illegal type combination");
1944 return mkty(INT, 0, 0);
1945 }
1946
1947 struct tylnk {
1948 struct tylnk *next;
1949 union dimfun df;
1950 };
1951
1952 /*
1953 * Retrieve all CM-separated argument types, sizes and dimensions and
1954 * put them in an array.
1955 * XXX - can only check first type level, side effects?
1956 */
1957 static union arglist *
arglist(NODE * n)1958 arglist(NODE *n)
1959 {
1960 union arglist *al;
1961 NODE *w = n, **ap;
1962 int num, cnt, i, j, k;
1963 TWORD ty;
1964
1965 #ifdef PCC_DEBUG
1966 if (pdebug) {
1967 printf("arglist %p\n", n);
1968 fwalk(n, eprint, 0);
1969 }
1970 #endif
1971 /* First: how much to allocate */
1972 for (num = cnt = 0, w = n; w->n_op == CM; w = w->n_left) {
1973 cnt++; /* Number of levels */
1974 num++; /* At least one per step */
1975 if (w->n_right->n_op == ELLIPSIS)
1976 continue;
1977 ty = w->n_right->n_type;
1978 if (ty == ENUMTY) {
1979 uerror("arg %d enum undeclared", cnt);
1980 ty = w->n_right->n_type = INT;
1981 }
1982 if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY)
1983 num++;
1984 while (!ISFTN(ty) && !ISARY(ty) && ty > BTMASK)
1985 ty = DECREF(ty);
1986 if (ty > BTMASK)
1987 num++;
1988 }
1989 cnt++;
1990 ty = w->n_type;
1991 if (ty == ENUMTY) {
1992 uerror("arg %d enum undeclared", cnt);
1993 ty = w->n_type = INT;
1994 }
1995 if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY)
1996 num++;
1997 while (!ISFTN(ty) && !ISARY(ty) && ty > BTMASK)
1998 ty = DECREF(ty);
1999 if (ty > BTMASK)
2000 num++;
2001 num += 2; /* TEND + last arg type */
2002
2003 /* Second: Create list to work on */
2004 ap = tmpalloc(sizeof(NODE *) * cnt);
2005 al = permalloc(sizeof(union arglist) * num);
2006 arglistcnt += num;
2007
2008 for (w = n, i = 0; w->n_op == CM; w = w->n_left)
2009 ap[i++] = w->n_right;
2010 ap[i] = w;
2011
2012 /* Third: Create actual arg list */
2013 for (k = 0, j = i; j >= 0; j--) {
2014 if (ap[j]->n_op == ELLIPSIS) {
2015 al[k++].type = TELLIPSIS;
2016 ap[j]->n_op = ICON; /* for tfree() */
2017 continue;
2018 }
2019 /* Convert arrays to pointers */
2020 if (ISARY(ap[j]->n_type)) {
2021 ap[j]->n_type += (PTR-ARY);
2022 ap[j]->n_df++;
2023 }
2024 /* Convert (silently) functions to pointers */
2025 if (ISFTN(ap[j]->n_type))
2026 ap[j]->n_type = INCREF(ap[j]->n_type);
2027 ty = ap[j]->n_type;
2028 #ifdef GCC_COMPAT
2029 if (ty == UNIONTY &&
2030 attr_find(ap[j]->n_ap, GCC_ATYP_TRANSP_UNION)){
2031 /* transparent unions must have compatible types
2032 * shortcut here: if pointers, set void *,
2033 * otherwise btype.
2034 */
2035 struct symtab *sp = strmemb(ap[j]->n_ap);
2036 ty = ISPTR(sp->stype) ? PTR|VOID : sp->stype;
2037 }
2038 #endif
2039 al[k++].type = ty;
2040 if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY)
2041 al[k++].sap = ap[j]->n_ap;
2042 while (!ISFTN(ty) && !ISARY(ty) && ty > BTMASK)
2043 ty = DECREF(ty);
2044 if (ty > BTMASK)
2045 al[k++].df = ap[j]->n_df;
2046 }
2047 al[k++].type = TNULL;
2048 if (k > num)
2049 cerror("arglist: k%d > num%d", k, num);
2050 tfree(n);
2051 #ifdef PCC_DEBUG
2052 if (pdebug)
2053 alprint(al, 0);
2054 #endif
2055 return al;
2056 }
2057
2058 static void
tylkadd(union dimfun dim,struct tylnk ** tylkp,int * ntdim)2059 tylkadd(union dimfun dim, struct tylnk **tylkp, int *ntdim)
2060 {
2061 (*tylkp)->next = tmpalloc(sizeof(struct tylnk));
2062 *tylkp = (*tylkp)->next;
2063 (*tylkp)->next = NULL;
2064 (*tylkp)->df = dim;
2065 (*ntdim)++;
2066 }
2067
2068 /*
2069 * build a type, and stash away dimensions,
2070 * from a parse tree of the declaration
2071 * the type is build top down, the dimensions bottom up
2072 */
2073 static void
tyreduce(NODE * p,struct tylnk ** tylkp,int * ntdim)2074 tyreduce(NODE *p, struct tylnk **tylkp, int *ntdim)
2075 {
2076 union dimfun dim;
2077 NODE *r = NULL;
2078 int o;
2079 TWORD t, q;
2080
2081 o = p->n_op;
2082 if (o == NAME) {
2083 p->n_qual = DECQAL(p->n_qual);
2084 return;
2085 }
2086
2087 t = INCREF(p->n_type);
2088 q = p->n_qual;
2089 switch (o) {
2090 case CALL:
2091 t += (FTN-PTR);
2092 dim.dfun = arglist(p->n_right);
2093 break;
2094 case UCALL:
2095 t += (FTN-PTR);
2096 dim.dfun = NULL;
2097 break;
2098 case LB:
2099 t += (ARY-PTR);
2100 if (p->n_right->n_op != ICON) {
2101 r = p->n_right;
2102 o = RB;
2103 } else {
2104 dim.ddim = (int)p->n_right->n_lval;
2105 nfree(p->n_right);
2106 #ifdef notdef
2107 /* XXX - check dimensions at usage time */
2108 if (dim.ddim == NOOFFSET && p->n_left->n_op == LB)
2109 uerror("null dimension");
2110 #endif
2111 }
2112 break;
2113 }
2114
2115 p->n_left->n_type = t;
2116 p->n_left->n_qual = INCQAL(q) | p->n_left->n_qual;
2117 tyreduce(p->n_left, tylkp, ntdim);
2118
2119 if (o == LB || o == UCALL || o == CALL)
2120 tylkadd(dim, tylkp, ntdim);
2121 if (o == RB) {
2122 dim.ddim = -1;
2123 tylkadd(dim, tylkp, ntdim);
2124 arrstk[arrstkp++] = r;
2125 }
2126
2127 p->n_sp = p->n_left->n_sp;
2128 p->n_type = p->n_left->n_type;
2129 p->n_qual = p->n_left->n_qual;
2130 }
2131
2132 /*
2133 * merge type typ with identifier idp.
2134 * idp is returned as a NAME node with correct types,
2135 * typ is untouched since multiple declarations uses it.
2136 * typ has type attributes, idp can never carry such attributes
2137 * so on return just a pointer to the typ attributes is returned.
2138 */
2139 NODE *
tymerge(NODE * typ,NODE * idp)2140 tymerge(NODE *typ, NODE *idp)
2141 {
2142 TWORD t;
2143 NODE *p;
2144 union dimfun *j;
2145 struct tylnk *base, tylnk, *tylkp;
2146 struct attr *bap;
2147 int ntdim, i;
2148
2149 #ifdef PCC_DEBUG
2150 if (ddebug > 2) {
2151 printf("tymerge(%p,%p)\n", typ, idp);
2152 fwalk(typ, eprint, 0);
2153 fwalk(idp, eprint, 0);
2154 }
2155 #endif
2156
2157 if (typ->n_op != TYPE)
2158 cerror("tymerge: arg 1");
2159
2160 bap = typ->n_ap;
2161
2162 idp->n_type = typ->n_type;
2163 idp->n_qual |= typ->n_qual;
2164
2165 tylkp = &tylnk;
2166 tylkp->next = NULL;
2167 ntdim = 0;
2168
2169 tyreduce(idp, &tylkp, &ntdim);
2170
2171 for (t = typ->n_type, j = typ->n_df; t&TMASK; t = DECREF(t))
2172 if (ISARY(t) || ISFTN(t))
2173 tylkadd(*j++, &tylkp, &ntdim);
2174
2175 if (ntdim) {
2176 union dimfun *a = permalloc(sizeof(union dimfun) * ntdim);
2177 dimfuncnt += ntdim;
2178 for (i = 0, base = tylnk.next; base; base = base->next, i++)
2179 a[i] = base->df;
2180 idp->n_df = a;
2181 } else
2182 idp->n_df = NULL;
2183
2184 /* now idp is a single node: fix up type */
2185 if ((t = ctype(idp->n_type)) != idp->n_type)
2186 idp->n_type = t;
2187
2188 if (idp->n_op != NAME) {
2189 for (p = idp->n_left; p->n_op != NAME; p = p->n_left)
2190 nfree(p);
2191 nfree(p);
2192 idp->n_op = NAME;
2193 }
2194 /* carefully not destroy any type attributes */
2195 if (idp->n_ap != NULL) {
2196 struct attr *ap = idp->n_ap;
2197 while (ap->next)
2198 ap = ap->next;
2199 ap->next = bap;
2200 } else
2201 idp->n_ap = bap;
2202
2203 return(idp);
2204 }
2205
2206 static NODE *
argcast(NODE * p,TWORD t,union dimfun * d,struct attr * ap)2207 argcast(NODE *p, TWORD t, union dimfun *d, struct attr *ap)
2208 {
2209 NODE *u, *r = talloc();
2210
2211 r->n_op = NAME;
2212 r->n_type = t;
2213 r->n_qual = 0; /* XXX */
2214 r->n_df = d;
2215 r->n_ap = ap;
2216
2217 u = buildtree(CAST, r, p);
2218 nfree(u->n_left);
2219 r = u->n_right;
2220 nfree(u);
2221 return r;
2222 }
2223
2224 #ifdef PCC_DEBUG
2225 /*
2226 * Print a prototype.
2227 */
2228 static void
alprint(union arglist * al,int in)2229 alprint(union arglist *al, int in)
2230 {
2231 TWORD t;
2232 int i = 0, j;
2233
2234 for (; al->type != TNULL; al++) {
2235 for (j = in; j > 0; j--)
2236 printf(" ");
2237 printf("arg %d: ", i++);
2238 t = al->type;
2239 tprint(t, 0);
2240 while (t > BTMASK) {
2241 if (ISARY(t)) {
2242 al++;
2243 printf(" dim %d ", al->df->ddim);
2244 } else if (ISFTN(t)) {
2245 al++;
2246 if (al->df->dfun) {
2247 printf("\n");
2248 alprint(al->df->dfun, in+1);
2249 }
2250 }
2251 t = DECREF(t);
2252 }
2253 if (ISSOU(t)) {
2254 al++;
2255 printf(" (size %d align %d)", (int)tsize(t, 0, al->sap),
2256 (int)talign(t, al->sap));
2257 }
2258 printf("\n");
2259 }
2260 if (in == 0)
2261 printf("end arglist\n");
2262 }
2263 #endif
2264
2265 int
suemeq(struct attr * s1,struct attr * s2)2266 suemeq(struct attr *s1, struct attr *s2)
2267 {
2268
2269 return (strmemb(s1) == strmemb(s2));
2270 }
2271
2272 /*
2273 * Sanity-check old-style args.
2274 */
2275 static NODE *
oldarg(NODE * p)2276 oldarg(NODE *p)
2277 {
2278 if (p->n_op == TYPE)
2279 uerror("type is not an argument");
2280 if (p->n_type == FLOAT)
2281 return cast(p, DOUBLE, p->n_qual);
2282 return p;
2283 }
2284
2285 /*
2286 * Do prototype checking and add conversions before calling a function.
2287 * Argument f is function and a is a CM-separated list of arguments.
2288 * Returns a merged node (via buildtree() of function and arguments.
2289 */
2290 NODE *
doacall(struct symtab * sp,NODE * f,NODE * a)2291 doacall(struct symtab *sp, NODE *f, NODE *a)
2292 {
2293 NODE *w, *r;
2294 union arglist *al;
2295 struct ap {
2296 struct ap *next;
2297 NODE *node;
2298 } *at, *apole = NULL;
2299 int argidx/* , hasarray = 0*/;
2300 TWORD type, arrt;
2301
2302 #ifdef PCC_DEBUG
2303 if (ddebug) {
2304 printf("doacall.\n");
2305 fwalk(f, eprint, 0);
2306 if (a)
2307 fwalk(a, eprint, 0);
2308 }
2309 #endif
2310
2311 /* First let MD code do something */
2312 calldec(f, a);
2313 /* XXX XXX hack */
2314 if ((f->n_op == CALL) &&
2315 f->n_left->n_op == ADDROF &&
2316 f->n_left->n_left->n_op == NAME &&
2317 (f->n_left->n_left->n_type & 0x7e0) == 0x4c0)
2318 goto build;
2319 /* XXX XXX hack */
2320
2321 /* Check for undefined or late defined enums */
2322 if (BTYPE(f->n_type) == ENUMTY) {
2323 /* not-yet check if declared enum */
2324 struct symtab *sq = strmemb(f->n_ap);
2325 if (sq->stype != ENUMTY)
2326 MODTYPE(f->n_type, sq->stype);
2327 if (BTYPE(f->n_type) == ENUMTY)
2328 uerror("enum %s not declared", sq->sname);
2329 }
2330
2331 /*
2332 * Do some basic checks.
2333 */
2334 if (f->n_df == NULL || (al = f->n_df[0].dfun) == NULL) {
2335 /*
2336 * Handle non-prototype declarations.
2337 */
2338 if (f->n_op == NAME && f->n_sp != NULL) {
2339 if (strncmp(f->n_sp->sname, "__builtin", 9) != 0 &&
2340 (f->n_sp->sflags & SINSYS) == 0)
2341 warner(Wmissing_prototypes, f->n_sp->sname);
2342 } else
2343 warner(Wmissing_prototypes, "<pointer>");
2344
2345 /* floats must be cast to double */
2346 if (a == NULL)
2347 goto build;
2348 if (a->n_op != CM) {
2349 a = oldarg(a);
2350 } else {
2351 for (w = a; w->n_left->n_op == CM; w = w->n_left)
2352 w->n_right = oldarg(w->n_right);
2353 w->n_left = oldarg(w->n_left);
2354 w->n_right = oldarg(w->n_right);
2355 }
2356 goto build;
2357 }
2358 if (al->type == VOID) {
2359 if (a != NULL)
2360 uerror("function takes no arguments");
2361 goto build; /* void function */
2362 } else {
2363 if (a == NULL) {
2364 uerror("function needs arguments");
2365 goto build;
2366 }
2367 }
2368 #ifdef PCC_DEBUG
2369 if (pdebug) {
2370 printf("arglist for %s\n",
2371 f->n_sp != NULL ? f->n_sp->sname : "function pointer");
2372 alprint(al, 0);
2373 }
2374 #endif
2375
2376 /*
2377 * Create a list of pointers to the nodes given as arg.
2378 */
2379 for (w = a; w->n_op == CM; w = w->n_left) {
2380 at = tmpalloc(sizeof(struct ap));
2381 at->node = w->n_right;
2382 at->next = apole;
2383 apole = at;
2384 }
2385 at = tmpalloc(sizeof(struct ap));
2386 at->node = w;
2387 at->next = apole;
2388 apole = at;
2389
2390 /*
2391 * Do the typechecking by walking up the list.
2392 */
2393 argidx = 1;
2394 while (al->type != TNULL) {
2395 if (al->type == TELLIPSIS) {
2396 /* convert the rest of float to double */
2397 for (; apole; apole = apole->next) {
2398 if (apole->node->n_type != FLOAT)
2399 continue;
2400 MKTY(apole->node, DOUBLE, 0, 0);
2401 }
2402 goto build;
2403 }
2404 if (apole == NULL) {
2405 uerror("too few arguments to function");
2406 goto build;
2407 }
2408 /* al = prototyp, apole = argument till ftn */
2409 /* type = argumentets typ, arrt = prototypens typ */
2410 type = apole->node->n_type;
2411 arrt = al->type;
2412 #if 0
2413 if ((hasarray = ISARY(arrt)))
2414 arrt += (PTR-ARY);
2415 #endif
2416 /* Taking addresses of arrays are meaningless in expressions */
2417 /* but people tend to do that and also use in prototypes */
2418 /* this is mostly a problem with typedefs */
2419 if (ISARY(type)) {
2420 if (ISPTR(arrt) && ISARY(DECREF(arrt)))
2421 type = INCREF(type);
2422 else
2423 type += (PTR-ARY);
2424 } else if (ISPTR(type) && !ISARY(DECREF(type)) &&
2425 ISPTR(arrt) && ISARY(DECREF(arrt))) {
2426 type += (ARY-PTR);
2427 type = INCREF(type);
2428 }
2429
2430 /* Check structs */
2431 if (type <= BTMASK && arrt <= BTMASK) {
2432 #ifndef NO_COMPLEX
2433 if ((type != arrt) && (ANYCX(apole->node) ||
2434 (arrt == STRTY &&
2435 attr_find(al[1].sap, ATTR_COMPLEX)))) {
2436 cxargfixup(apole->node, arrt, al[1].sap);
2437 } else
2438 #endif
2439 if (type != arrt) {
2440 if (ISSOU(BTYPE(type)) || ISSOU(BTYPE(arrt))) {
2441 incomp: uerror("incompatible types for arg %d",
2442 argidx);
2443 } else {
2444 MKTY(apole->node, arrt, 0, 0)
2445 }
2446 #ifndef NO_COMPLEX
2447 } else if (type == STRTY &&
2448 attr_find(apole->node->n_ap, ATTR_COMPLEX) &&
2449 attr_find(al[1].sap, ATTR_COMPLEX)) {
2450 /* Both are complex */
2451 if (strmemb(apole->node->n_ap)->stype !=
2452 strmemb(al[1].sap)->stype) {
2453 /* must convert to correct type */
2454 w = talloc();
2455 *w = *apole->node;
2456 w = mkcmplx(w,
2457 strmemb(al[1].sap)->stype);
2458 *apole->node = *w;
2459 nfree(w);
2460 }
2461 goto out;
2462 #endif
2463 } else if (ISSOU(BTYPE(type))) {
2464 if (!suemeq(apole->node->n_ap, al[1].sap))
2465 goto incomp;
2466 }
2467 goto out;
2468 }
2469
2470 /* XXX should (recusively) check return type and arg list of
2471 func ptr arg XXX */
2472 if (ISFTN(DECREF(arrt)) && ISFTN(type))
2473 type = INCREF(type);
2474
2475 /* Hereafter its only pointers (or arrays) left */
2476 /* Check for struct/union intermixing with other types */
2477 if (((type <= BTMASK) && ISSOU(BTYPE(type))) ||
2478 ((arrt <= BTMASK) && ISSOU(BTYPE(arrt))))
2479 goto incomp;
2480
2481 /* Check for struct/union compatibility */
2482 if (type == arrt) {
2483 if (ISSOU(BTYPE(type))) {
2484 if (suemeq(apole->node->n_ap, al[1].sap))
2485 goto out;
2486 } else
2487 goto out;
2488 }
2489 if (BTYPE(arrt) == VOID && type > BTMASK)
2490 goto skip; /* void *f = some pointer */
2491 if (arrt > BTMASK && BTYPE(type) == VOID)
2492 goto skip; /* some *f = void pointer */
2493 if (apole->node->n_op == ICON && apole->node->n_lval == 0)
2494 goto skip; /* Anything assigned a zero */
2495
2496 if ((type & ~BTMASK) == (arrt & ~BTMASK)) {
2497 /* do not complain for pointers with signedness */
2498 if ((DEUNSIGN(BTYPE(type)) == DEUNSIGN(BTYPE(arrt))) &&
2499 (BTYPE(type) != BTYPE(arrt))) {
2500 warner(Wpointer_sign);
2501 goto skip;
2502 }
2503 }
2504
2505 werror("implicit conversion of argument %d due to prototype",
2506 argidx);
2507
2508 skip: if (ISSOU(BTYPE(arrt))) {
2509 MKTY(apole->node, arrt, 0, al[1].sap)
2510 } else {
2511 MKTY(apole->node, arrt, 0, 0)
2512 }
2513
2514 out: al++;
2515 if (ISSOU(BTYPE(arrt)))
2516 al++;
2517 #if 0
2518 while (arrt > BTMASK && !ISFTN(arrt))
2519 arrt = DECREF(arrt);
2520 if (ISFTN(arrt) || hasarray)
2521 al++;
2522 #else
2523 while (arrt > BTMASK) {
2524 if (ISARY(arrt) || ISFTN(arrt)) {
2525 al++;
2526 break;
2527 }
2528 arrt = DECREF(arrt);
2529 }
2530 #endif
2531 apole = apole->next;
2532 argidx++;
2533 }
2534 if (apole != NULL)
2535 uerror("too many arguments to function");
2536
2537 build: if (sp != NULL && (sp->sflags & SINLINE) && (w = inlinetree(sp, f, a)))
2538 return w;
2539 return buildtree(a == NIL ? UCALL : CALL, f, a);
2540 }
2541
2542 static int
chk2(TWORD type,union dimfun * dsym,union dimfun * ddef)2543 chk2(TWORD type, union dimfun *dsym, union dimfun *ddef)
2544 {
2545 while (type > BTMASK) {
2546 switch (type & TMASK) {
2547 case ARY:
2548 /* may be declared without dimension */
2549 if (dsym->ddim == NOOFFSET)
2550 dsym->ddim = ddef->ddim;
2551 if (dsym->ddim < 0 && ddef->ddim < 0)
2552 ; /* dynamic arrays as arguments */
2553 else if (ddef->ddim > 0 && dsym->ddim != ddef->ddim)
2554 return 1;
2555 dsym++, ddef++;
2556 break;
2557 case FTN:
2558 /* old-style function headers with function pointers
2559 * will most likely not have a prototype.
2560 * This is not considered an error. */
2561 if (ddef->dfun == NULL) {
2562 #ifdef notyet
2563 werror("declaration not a prototype");
2564 #endif
2565 } else if (chkftn(dsym->dfun, ddef->dfun))
2566 return 1;
2567 dsym++, ddef++;
2568 break;
2569 }
2570 type = DECREF(type);
2571 }
2572 return 0;
2573 }
2574
2575 /*
2576 * Compare two function argument lists to see if they match.
2577 */
2578 int
chkftn(union arglist * usym,union arglist * udef)2579 chkftn(union arglist *usym, union arglist *udef)
2580 {
2581 TWORD t2;
2582 int ty, tyn;
2583
2584 if (usym == NULL)
2585 return 0;
2586 if (cftnsp != NULL && udef == NULL && usym->type == VOID)
2587 return 0; /* foo() { function with foo(void); prototype */
2588 if (udef == NULL && usym->type != TNULL)
2589 return 1;
2590 while (usym->type != TNULL) {
2591 if (usym->type == udef->type)
2592 goto done;
2593 /*
2594 * If an old-style declaration, then all types smaller than
2595 * int are given as int parameters.
2596 */
2597 if (intcompare) {
2598 ty = BTYPE(usym->type);
2599 tyn = BTYPE(udef->type);
2600 if (ty == tyn || ty != INT)
2601 return 1;
2602 if (tyn == CHAR || tyn == UCHAR ||
2603 tyn == SHORT || tyn == USHORT)
2604 goto done;
2605 return 1;
2606 } else
2607 return 1;
2608
2609 done: ty = BTYPE(usym->type);
2610 t2 = usym->type;
2611 if (ISSOU(ty)) {
2612 usym++, udef++;
2613 if (suemeq(usym->sap, udef->sap) == 0)
2614 return 1;
2615 }
2616
2617 while (!ISFTN(t2) && !ISARY(t2) && t2 > BTMASK)
2618 t2 = DECREF(t2);
2619 if (t2 > BTMASK) {
2620 usym++, udef++;
2621 if (chk2(t2, usym->df, udef->df))
2622 return 1;
2623 }
2624 usym++, udef++;
2625 }
2626 if (usym->type != udef->type)
2627 return 1;
2628 return 0;
2629 }
2630
2631 void
fixtype(NODE * p,int class)2632 fixtype(NODE *p, int class)
2633 {
2634 unsigned int t, type;
2635 int mod1, mod2;
2636 /* fix up the types, and check for legality */
2637
2638 /* forward declared enums */
2639 if (BTYPE(p->n_sp->stype) == ENUMTY) {
2640 MODTYPE(p->n_sp->stype, strmemb(p->n_sp->sap)->stype);
2641 }
2642
2643 if( (type = p->n_type) == UNDEF ) return;
2644 if ((mod2 = (type&TMASK))) {
2645 t = DECREF(type);
2646 while( mod1=mod2, mod2 = (t&TMASK) ){
2647 if( mod1 == ARY && mod2 == FTN ){
2648 uerror( "array of functions is illegal" );
2649 type = 0;
2650 }
2651 else if( mod1 == FTN && ( mod2 == ARY || mod2 == FTN ) ){
2652 uerror( "function returns illegal type" );
2653 type = 0;
2654 }
2655 t = DECREF(t);
2656 }
2657 }
2658
2659 /* detect function arguments, watching out for structure declarations */
2660 if (rpole && ISFTN(type)) {
2661 uerror("function illegal in structure or union");
2662 type = INCREF(type);
2663 }
2664 p->n_type = type;
2665 }
2666
2667 /*
2668 * give undefined version of class
2669 */
2670 int
uclass(int class)2671 uclass(int class)
2672 {
2673 if (class == SNULL)
2674 return(EXTERN);
2675 else if (class == STATIC)
2676 return(USTATIC);
2677 else
2678 return(class);
2679 }
2680
2681 int
fixclass(int class,TWORD type)2682 fixclass(int class, TWORD type)
2683 {
2684 extern int fun_inline;
2685
2686 /* first, fix null class */
2687 if (class == SNULL) {
2688 if (fun_inline && ISFTN(type))
2689 return SNULL;
2690 if (rpole)
2691 cerror("field8");
2692 else if (blevel == 0)
2693 class = EXTDEF;
2694 else
2695 class = AUTO;
2696 }
2697
2698 /* now, do general checking */
2699
2700 if( ISFTN( type ) ){
2701 switch( class ) {
2702 default:
2703 uerror( "function has illegal storage class" );
2704 case AUTO:
2705 class = EXTERN;
2706 case EXTERN:
2707 case EXTDEF:
2708 case TYPEDEF:
2709 case STATIC:
2710 case USTATIC:
2711 ;
2712 }
2713 }
2714
2715 if (class & FIELD) {
2716 cerror("field3");
2717 }
2718
2719 switch (class) {
2720
2721 case MOS:
2722 case MOU:
2723 cerror("field4");
2724
2725 case REGISTER:
2726 if (blevel == 0)
2727 uerror("illegal register declaration");
2728 if (blevel == 1)
2729 return(PARAM);
2730 else
2731 return(REGISTER);
2732
2733 case AUTO:
2734 if( blevel < 2 ) uerror( "illegal ULABEL class" );
2735 return( class );
2736
2737 case EXTERN:
2738 case STATIC:
2739 case EXTDEF:
2740 case TYPEDEF:
2741 case USTATIC:
2742 case PARAM:
2743 return( class );
2744
2745 default:
2746 cerror( "illegal class: %d", class );
2747 /* NOTREACHED */
2748
2749 }
2750 return 0; /* XXX */
2751 }
2752
2753 /*
2754 * Generates a goto statement; sets up label number etc.
2755 */
2756 void
gotolabel(char * name)2757 gotolabel(char *name)
2758 {
2759 struct symtab *s = lookup(name, SLBLNAME);
2760
2761 if (s->soffset == 0) {
2762 s->soffset = -getlab();
2763 s->sclass = STATIC;
2764 }
2765 branch(s->soffset < 0 ? -s->soffset : s->soffset);
2766 }
2767
2768 /*
2769 * Sets a label for gotos.
2770 */
2771 void
deflabel(char * name,NODE * p)2772 deflabel(char *name, NODE *p)
2773 {
2774 struct symtab *s = lookup(name, SLBLNAME);
2775
2776 #ifdef GCC_COMPAT
2777 s->sap = gcc_attr_parse(p);
2778 #endif
2779 if (s->soffset > 0)
2780 uerror("label '%s' redefined", name);
2781 if (s->soffset == 0) {
2782 s->soffset = getlab();
2783 s->sclass = STATIC;
2784 }
2785 if (s->soffset < 0)
2786 s->soffset = -s->soffset;
2787 plabel( s->soffset);
2788 }
2789
2790 struct symtab *
getsymtab(char * name,int flags)2791 getsymtab(char *name, int flags)
2792 {
2793 struct symtab *s;
2794
2795 if (flags & STEMP) {
2796 s = tmpalloc(sizeof(struct symtab));
2797 } else {
2798 s = permalloc(sizeof(struct symtab));
2799 symtabcnt++;
2800 }
2801 s->sname = name;
2802 s->soname = NULL;
2803 s->snext = NULL;
2804 s->stype = UNDEF;
2805 s->squal = 0;
2806 s->sclass = SNULL;
2807 s->sflags = (short)(flags & SMASK);
2808 s->soffset = 0;
2809 s->slevel = (char)blevel;
2810 s->sdf = NULL;
2811 s->sap = NULL;
2812 return s;
2813 }
2814
2815 int
fldchk(int sz)2816 fldchk(int sz)
2817 {
2818 if (rpole->rsou != STNAME && rpole->rsou != UNAME)
2819 uerror("field outside of structure");
2820 if (sz < 0 || sz >= FIELD) {
2821 uerror("illegal field size");
2822 return 1;
2823 }
2824 return 0;
2825 }
2826
2827 #ifdef PCC_DEBUG
2828 static char *
2829 ccnames[] = { /* names of storage classes */
2830 "SNULL",
2831 "AUTO",
2832 "EXTERN",
2833 "STATIC",
2834 "REGISTER",
2835 "EXTDEF",
2836 "LABEL",
2837 "ULABEL",
2838 "MOS",
2839 "PARAM",
2840 "STNAME",
2841 "MOU",
2842 "UNAME",
2843 "TYPEDEF",
2844 "FORTRAN",
2845 "ENAME",
2846 "MOE",
2847 "UFORTRAN",
2848 "USTATIC",
2849 };
2850
2851 char *
scnames(int c)2852 scnames(int c)
2853 {
2854 /* return the name for storage class c */
2855 static char buf[12];
2856 if( c&FIELD ){
2857 snprintf( buf, sizeof(buf), "FIELD[%d]", c&FLDSIZ );
2858 return( buf );
2859 }
2860 return( ccnames[c] );
2861 }
2862 #endif
2863
2864 #if 0
2865 static char *stack_chk_fail = "__stack_smash_handler";
2866 static char *stack_chk_guard = "__guard";
2867 #else
2868 static char *stack_chk_fail = "__stack_chk_fail";
2869 static char *stack_chk_guard = "__stack_chk_guard";
2870 #endif
2871 static char *stack_chk_canary = "__stack_chk_canary";
2872
2873 void
sspinit(void)2874 sspinit(void)
2875 {
2876 NODE *p;
2877
2878 p = block(NAME, NIL, NIL, FTN+VOID, 0, 0);
2879 p->n_sp = lookup(stack_chk_fail, SNORMAL);
2880 defid(p, EXTERN);
2881 nfree(p);
2882
2883 p = block(NAME, NIL, NIL, INT, 0, 0);
2884 p->n_sp = lookup(stack_chk_guard, SNORMAL);
2885 defid(p, EXTERN);
2886 nfree(p);
2887 }
2888
2889 void
sspstart(void)2890 sspstart(void)
2891 {
2892 NODE *p, *q;
2893
2894 q = block(NAME, NIL, NIL, INT, 0, 0);
2895 q->n_sp = lookup(stack_chk_guard, SNORMAL);
2896 q = clocal(q);
2897
2898 p = block(REG, NIL, NIL, INCREF(INT), 0, 0);
2899 p->n_lval = 0;
2900 p->n_rval = FPREG;
2901 p = cast(p, INT, 0);
2902 q = buildtree(ER, p, q);
2903
2904 p = block(NAME, NIL, NIL, INT, 0, 0);
2905 p->n_qual = VOL >> TSHIFT;
2906 p->n_sp = lookup(stack_chk_canary, SNORMAL);
2907 defid(p, AUTO);
2908 p = clocal(p);
2909 ecomp(buildtree(ASSIGN, p, q));
2910 }
2911
2912 void
sspend(void)2913 sspend(void)
2914 {
2915 NODE *p, *q;
2916 TWORD t;
2917 int lab;
2918
2919 if (retlab != NOLAB) {
2920 plabel(retlab);
2921 retlab = getlab();
2922 }
2923
2924 t = DECREF(cftnsp->stype);
2925 if (t == BOOL)
2926 t = BOOL_TYPE;
2927
2928 p = block(NAME, NIL, NIL, INT, 0, 0);
2929 p->n_sp = lookup(stack_chk_canary, SNORMAL);
2930 p = clocal(p);
2931
2932 q = block(REG, NIL, NIL, INCREF(INT), 0, 0);
2933 q->n_lval = 0;
2934 q->n_rval = FPREG;
2935 q = cast(q, INT, 0);
2936 q = buildtree(ER, p, q);
2937
2938 p = block(NAME, NIL, NIL, INT, 0, 0);
2939 p->n_sp = lookup(stack_chk_guard, SNORMAL);
2940 p = clocal(p);
2941
2942 lab = getlab();
2943 cbranch(buildtree(EQ, p, q), bcon(lab));
2944
2945 p = block(NAME, NIL, NIL, FTN+VOID, 0, 0);
2946 p->n_sp = lookup(stack_chk_fail, SNORMAL);
2947 p = clocal(p);
2948
2949 q = eve(bdty(STRING, cftnsp->sname, 0));
2950 ecomp(buildtree(CALL, p, q));
2951
2952 plabel(lab);
2953 }
2954
2955 /*
2956 * Allocate on the permanent heap for inlines, otherwise temporary heap.
2957 */
2958 void *
blkalloc(int size)2959 blkalloc(int size)
2960 {
2961 return isinlining || blevel < 2 ? permalloc(size) : tmpalloc(size);
2962 }
2963
2964 /*
2965 * Allocate on the permanent heap for inlines, otherwise temporary heap.
2966 */
2967 void *
inlalloc(int size)2968 inlalloc(int size)
2969 {
2970 return isinlining ? permalloc(size) : tmpalloc(size);
2971 }
2972
2973 struct attr *
attr_new(int type,int nelem)2974 attr_new(int type, int nelem)
2975 {
2976 struct attr *ap;
2977 int sz;
2978
2979 sz = sizeof(struct attr) + nelem * sizeof(union aarg);
2980
2981 ap = memset(blkalloc(sz), 0, sz);
2982 ap->atype = type;
2983 return ap;
2984 }
2985
2986 /*
2987 * Add attribute list new before old and return new.
2988 */
2989 struct attr *
attr_add(struct attr * old,struct attr * new)2990 attr_add(struct attr *old, struct attr *new)
2991 {
2992 struct attr *ap;
2993
2994 if (new == NULL)
2995 return old; /* nothing to add */
2996
2997 for (ap = new; ap->next; ap = ap->next)
2998 ;
2999 ap->next = old;
3000 return new;
3001 }
3002
3003 /*
3004 * Search for attribute type in list ap. Return entry or NULL.
3005 */
3006 struct attr *
attr_find(struct attr * ap,int type)3007 attr_find(struct attr *ap, int type)
3008 {
3009
3010 for (; ap && ap->atype != type; ap = ap->next)
3011 ;
3012 return ap;
3013 }
3014
3015 /*
3016 * Copy an attribute struct.
3017 * Return destination.
3018 */
3019 struct attr *
attr_copy(struct attr * aps,struct attr * apd,int n)3020 attr_copy(struct attr *aps, struct attr *apd, int n)
3021 {
3022 int sz = sizeof(struct attr) + n * sizeof(union aarg);
3023 return memcpy(apd, aps, sz);
3024 }
3025
3026 /*
3027 * Duplicate an attribute, like strdup.
3028 */
3029 struct attr *
attr_dup(struct attr * ap,int n)3030 attr_dup(struct attr *ap, int n)
3031 {
3032 int sz = sizeof(struct attr) + n * sizeof(union aarg);
3033 ap = memcpy(blkalloc(sz), ap, sz);
3034 ap->next = NULL;
3035 return ap;
3036 }
3037
3038 /*
3039 * Fetch pointer to first member in a struct list.
3040 */
3041 struct symtab *
strmemb(struct attr * ap)3042 strmemb(struct attr *ap)
3043 {
3044
3045 if ((ap = attr_find(ap, ATTR_STRUCT)) == NULL)
3046 cerror("strmemb");
3047 return ap->amlist;
3048 }
3049
3050 #ifndef NO_COMPLEX
3051
3052 static char *real, *imag;
3053 static struct symtab *cxsp[3], *cxmul[3], *cxdiv[3];
3054 static char *cxnmul[] = { "__mulsc3", "__muldc3", "__mulxc3" };
3055 static char *cxndiv[] = { "__divsc3", "__divdc3", "__divxc3" };
3056 /*
3057 * As complex numbers internally are handled as structs, create
3058 * these by hand-crafting them.
3059 */
3060 void
complinit(void)3061 complinit(void)
3062 {
3063 struct attr *ap;
3064 struct rstack *rp;
3065 NODE *p, *q;
3066 char *n[] = { "0f", "0d", "0l" };
3067 int i, d_debug;
3068
3069 d_debug = ddebug;
3070 ddebug = 0;
3071 real = addname("__real");
3072 imag = addname("__imag");
3073 p = block(NAME, NIL, NIL, FLOAT, 0, 0);
3074 for (i = 0; i < 3; i++) {
3075 p->n_type = FLOAT+i;
3076 rpole = rp = bstruct(NULL, STNAME, NULL);
3077 soumemb(p, real, 0);
3078 soumemb(p, imag, 0);
3079 q = dclstruct(rp);
3080 cxsp[i] = q->n_sp = lookup(addname(n[i]), 0);
3081 defid(q, TYPEDEF);
3082 ap = attr_new(ATTR_COMPLEX, 0);
3083 q->n_sp->sap = attr_add(q->n_sp->sap, ap);
3084 nfree(q);
3085 }
3086 /* create function declarations for external ops */
3087 for (i = 0; i < 3; i++) {
3088 cxnmul[i] = addname(cxnmul[i]);
3089 p->n_sp = cxmul[i] = lookup(cxnmul[i], 0);
3090 p->n_type = FTN|STRTY;
3091 p->n_ap = cxsp[i]->sap;
3092 p->n_df = cxsp[i]->sdf;
3093 defid2(p, EXTERN, 0);
3094 cxmul[i]->sdf = permalloc(sizeof(union dimfun));
3095 cxmul[i]->sdf->dfun = NULL;
3096 cxndiv[i] = addname(cxndiv[i]);
3097 p->n_sp = cxdiv[i] = lookup(cxndiv[i], 0);
3098 p->n_type = FTN|STRTY;
3099 p->n_ap = cxsp[i]->sap;
3100 p->n_df = cxsp[i]->sdf;
3101 defid2(p, EXTERN, 0);
3102 cxdiv[i]->sdf = permalloc(sizeof(union dimfun));
3103 cxdiv[i]->sdf->dfun = NULL;
3104 }
3105 nfree(p);
3106 ddebug = d_debug;
3107 }
3108
3109 static TWORD
maxtt(NODE * p)3110 maxtt(NODE *p)
3111 {
3112 TWORD t;
3113
3114 t = ANYCX(p) ? strmemb(p->n_ap)->stype : p->n_type;
3115 t = BTYPE(t);
3116 if (t == VOID)
3117 t = CHAR; /* pointers */
3118 if (ISITY(t))
3119 t -= (FIMAG - FLOAT);
3120 return t;
3121 }
3122
3123 /*
3124 * Return the highest real floating point type.
3125 * Known that at least one type is complex or imaginary.
3126 */
3127 static TWORD
maxtyp(NODE * l,NODE * r)3128 maxtyp(NODE *l, NODE *r)
3129 {
3130 TWORD tl, tr, t;
3131
3132 tl = maxtt(l);
3133 tr = maxtt(r);
3134 t = tl > tr ? tl : tr;
3135 if (!ISFTY(t))
3136 cerror("maxtyp");
3137 return t;
3138 }
3139
3140 /*
3141 * Fetch space on stack for complex struct.
3142 */
3143 static NODE *
cxstore(TWORD t)3144 cxstore(TWORD t)
3145 {
3146 struct symtab s;
3147
3148 s = *cxsp[t - FLOAT];
3149 s.sclass = AUTO;
3150 s.soffset = NOOFFSET;
3151 oalloc(&s, &autooff);
3152 return nametree(&s);
3153 }
3154
3155 #define comop(x,y) buildtree(COMOP, x, y)
3156
3157 /*
3158 * Convert node p to complex type dt.
3159 */
3160 static NODE *
mkcmplx(NODE * p,TWORD dt)3161 mkcmplx(NODE *p, TWORD dt)
3162 {
3163 NODE *q, *r, *i, *t;
3164
3165 if (!ANYCX(p)) {
3166 /* Not complex, convert to complex on stack */
3167 q = cxstore(dt);
3168 if (ISITY(p->n_type)) {
3169 p->n_type = p->n_type - FIMAG + FLOAT;
3170 r = bcon(0);
3171 i = p;
3172 } else {
3173 if (ISPTR(p->n_type))
3174 p = cast(p, INTPTR, 0);
3175 r = p;
3176 i = bcon(0);
3177 }
3178 p = buildtree(ASSIGN, structref(ccopy(q), DOT, real), r);
3179 p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, imag), i));
3180 p = comop(p, q);
3181 } else {
3182 if (strmemb(p->n_ap)->stype != dt) {
3183 q = cxstore(dt);
3184 p = buildtree(ADDROF, p, NIL);
3185 t = tempnode(0, p->n_type, p->n_df, p->n_ap);
3186 p = buildtree(ASSIGN, ccopy(t), p);
3187 p = comop(p, buildtree(ASSIGN,
3188 structref(ccopy(q), DOT, real),
3189 structref(ccopy(t), STREF, real)));
3190 p = comop(p, buildtree(ASSIGN,
3191 structref(ccopy(q), DOT, imag),
3192 structref(t, STREF, imag)));
3193 p = comop(p, q);
3194 }
3195 }
3196 return p;
3197 }
3198
3199 static NODE *
cxasg(NODE * l,NODE * r)3200 cxasg(NODE *l, NODE *r)
3201 {
3202 TWORD tl, tr;
3203
3204 tl = strattr(l->n_ap) ? strmemb(l->n_ap)->stype : 0;
3205 tr = strattr(r->n_ap) ? strmemb(r->n_ap)->stype : 0;
3206
3207 if (ANYCX(l) && ANYCX(r) && tl != tr) {
3208 /* different types in structs */
3209 r = mkcmplx(r, tl);
3210 } else if (!ANYCX(l))
3211 r = structref(r, DOT, ISITY(l->n_type) ? imag : real);
3212 else if (!ANYCX(r))
3213 r = mkcmplx(r, tl);
3214 return buildtree(ASSIGN, l, r);
3215 }
3216
3217 /*
3218 * Fixup complex operations.
3219 * At least one operand is complex.
3220 */
3221 NODE *
cxop(int op,NODE * l,NODE * r)3222 cxop(int op, NODE *l, NODE *r)
3223 {
3224 TWORD mxtyp;
3225 NODE *p, *q;
3226 NODE *ltemp, *rtemp;
3227 NODE *real_l, *imag_l;
3228 NODE *real_r, *imag_r;
3229
3230 if (op == ASSIGN)
3231 return cxasg(l, r);
3232
3233 mxtyp = maxtyp(l, r);
3234 l = mkcmplx(l, mxtyp);
3235 if (op != UMINUS)
3236 r = mkcmplx(r, mxtyp);
3237
3238 if (op == COLON)
3239 return buildtree(COLON, l, r);
3240
3241 /* put a pointer to left and right elements in a TEMP */
3242 l = buildtree(ADDROF, l, NIL);
3243 ltemp = tempnode(0, l->n_type, l->n_df, l->n_ap);
3244 l = buildtree(ASSIGN, ccopy(ltemp), l);
3245
3246 if (op != UMINUS) {
3247 r = buildtree(ADDROF, r, NIL);
3248 rtemp = tempnode(0, r->n_type, r->n_df, r->n_ap);
3249 r = buildtree(ASSIGN, ccopy(rtemp), r);
3250
3251 p = comop(l, r);
3252 } else
3253 p = l;
3254
3255 /* create the four trees needed for calculation */
3256 real_l = structref(ccopy(ltemp), STREF, real);
3257 imag_l = structref(ltemp, STREF, imag);
3258 if (op != UMINUS) {
3259 real_r = structref(ccopy(rtemp), STREF, real);
3260 imag_r = structref(rtemp, STREF, imag);
3261 }
3262
3263 /* get storage on stack for the result */
3264 q = cxstore(mxtyp);
3265
3266 switch (op) {
3267 case NE:
3268 case EQ:
3269 tfree(q);
3270 p = buildtree(op, comop(p, real_l), real_r);
3271 q = buildtree(op, imag_l, imag_r);
3272 p = buildtree(op == EQ ? ANDAND : OROR, p, q);
3273 return p;
3274
3275 case ANDAND:
3276 case OROR: /* go via EQ to get INT of it */
3277 tfree(q);
3278 p = buildtree(NE, comop(p, real_l), bcon(0)); /* gets INT */
3279 q = buildtree(NE, imag_l, bcon(0));
3280 p = buildtree(OR, p, q);
3281
3282 q = buildtree(NE, real_r, bcon(0));
3283 q = buildtree(OR, q, buildtree(NE, imag_r, bcon(0)));
3284
3285 p = buildtree(op, p, q);
3286 return p;
3287
3288 case UMINUS:
3289 p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, real),
3290 buildtree(op, real_l, NIL)));
3291 p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, imag),
3292 buildtree(op, imag_l, NIL)));
3293 break;
3294
3295 case PLUS:
3296 case MINUS:
3297 p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, real),
3298 buildtree(op, real_l, real_r)));
3299 p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, imag),
3300 buildtree(op, imag_l, imag_r)));
3301 break;
3302
3303 case MUL:
3304 case DIV:
3305 /* Complex mul is "complex" */
3306 /* (u+iv)*(x+iy)=((u*x)-(v*y))+i(v*x+y*u) */
3307 /* Complex div is even more "complex" */
3308 /* (u+iv)/(x+iy)=(u*x+v*y)/(x*x+y*y)+i((v*x-u*y)/(x*x+y*y)) */
3309 /* but we need to do it via a subroutine */
3310 tfree(q);
3311 p = buildtree(CM, comop(p, real_l), imag_l);
3312 p = buildtree(CM, p, real_r);
3313 p = buildtree(CM, p, imag_r);
3314 q = nametree(op == DIV ?
3315 cxdiv[mxtyp-FLOAT] : cxmul[mxtyp-FLOAT]);
3316 return buildtree(CALL, q, p);
3317 break;
3318 default:
3319 uerror("illegal operator %s", copst(op));
3320 }
3321 return comop(p, q);
3322 }
3323
3324 /*
3325 * Fixup imaginary operations.
3326 * At least one operand is imaginary, none is complex.
3327 */
3328 NODE *
imop(int op,NODE * l,NODE * r)3329 imop(int op, NODE *l, NODE *r)
3330 {
3331 NODE *p, *q;
3332 TWORD mxtyp;
3333 int li, ri;
3334
3335 li = ri = 0;
3336 if (ISITY(l->n_type))
3337 li = 1, l->n_type = l->n_type - (FIMAG-FLOAT);
3338 if (ISITY(r->n_type))
3339 ri = 1, r->n_type = r->n_type - (FIMAG-FLOAT);
3340
3341 mxtyp = maxtyp(l, r);
3342 switch (op) {
3343 case ASSIGN:
3344 /* if both are imag, store value, otherwise store 0.0 */
3345 if (!(li && ri)) {
3346 tfree(r);
3347 r = bcon(0);
3348 }
3349 p = buildtree(ASSIGN, l, r);
3350 p->n_type += (FIMAG-FLOAT);
3351 break;
3352
3353 case PLUS:
3354 if (li && ri) {
3355 p = buildtree(PLUS, l, r);
3356 p->n_type += (FIMAG-FLOAT);
3357 } else {
3358 /* If one is imaginary and one is real, make complex */
3359 if (li)
3360 q = l, l = r, r = q; /* switch */
3361 q = cxstore(mxtyp);
3362 p = buildtree(ASSIGN,
3363 structref(ccopy(q), DOT, real), l);
3364 p = comop(p, buildtree(ASSIGN,
3365 structref(ccopy(q), DOT, imag), r));
3366 p = comop(p, q);
3367 }
3368 break;
3369
3370 case MINUS:
3371 if (li && ri) {
3372 p = buildtree(MINUS, l, r);
3373 p->n_type += (FIMAG-FLOAT);
3374 } else if (li) {
3375 q = cxstore(mxtyp);
3376 p = buildtree(ASSIGN, structref(ccopy(q), DOT, real),
3377 buildtree(UMINUS, r, NIL));
3378 p = comop(p, buildtree(ASSIGN,
3379 structref(ccopy(q), DOT, imag), l));
3380 p = comop(p, q);
3381 } else /* if (ri) */ {
3382 q = cxstore(mxtyp);
3383 p = buildtree(ASSIGN,
3384 structref(ccopy(q), DOT, real), l);
3385 p = comop(p, buildtree(ASSIGN,
3386 structref(ccopy(q), DOT, imag),
3387 buildtree(UMINUS, r, NIL)));
3388 p = comop(p, q);
3389 }
3390 break;
3391
3392 case MUL:
3393 p = buildtree(MUL, l, r);
3394 if (li && ri)
3395 p = buildtree(UMINUS, p, NIL);
3396 if (li ^ ri)
3397 p->n_type += (FIMAG-FLOAT);
3398 break;
3399
3400 case DIV:
3401 p = buildtree(DIV, l, r);
3402 if (ri && !li)
3403 p = buildtree(UMINUS, p, NIL);
3404 if (li ^ ri)
3405 p->n_type += (FIMAG-FLOAT);
3406 break;
3407
3408 case EQ:
3409 case NE:
3410 case LT:
3411 case LE:
3412 case GT:
3413 case GE:
3414 if (li ^ ri) { /* always 0 */
3415 tfree(l);
3416 tfree(r);
3417 p = bcon(0);
3418 } else
3419 p = buildtree(op, l, r);
3420 break;
3421
3422 default:
3423 cerror("imop");
3424 p = NULL;
3425 }
3426 return p;
3427 }
3428
3429 NODE *
cxelem(int op,NODE * p)3430 cxelem(int op, NODE *p)
3431 {
3432
3433 if (ANYCX(p)) {
3434 p = structref(p, DOT, op == XREAL ? real : imag);
3435 } else if (op == XIMAG) {
3436 /* XXX sanitycheck? */
3437 tfree(p);
3438 p = bcon(0);
3439 }
3440 return p;
3441 }
3442
3443 NODE *
cxconj(NODE * p)3444 cxconj(NODE *p)
3445 {
3446 NODE *q, *r;
3447
3448 /* XXX side effects? */
3449 q = cxstore(strmemb(p->n_ap)->stype);
3450 r = buildtree(ASSIGN, structref(ccopy(q), DOT, real),
3451 structref(ccopy(p), DOT, real));
3452 r = comop(r, buildtree(ASSIGN, structref(ccopy(q), DOT, imag),
3453 buildtree(UMINUS, structref(p, DOT, imag), NIL)));
3454 return comop(r, q);
3455 }
3456
3457 /*
3458 * Prepare for return.
3459 * There may be implicit casts to other types.
3460 */
3461 NODE *
cxret(NODE * p,NODE * q)3462 cxret(NODE *p, NODE *q)
3463 {
3464 if (ANYCX(q)) { /* Return complex type */
3465 p = mkcmplx(p, strmemb(q->n_ap)->stype);
3466 } else if (q->n_type < STRTY || ISITY(q->n_type)) { /* real or imag */
3467 p = structref(p, DOT, ISITY(q->n_type) ? imag : real);
3468 if (p->n_type != q->n_type)
3469 p = cast(p, q->n_type, 0);
3470 } else
3471 cerror("cxred failing type");
3472 return p;
3473 }
3474
3475 /*
3476 * either p1 or p2 is complex, so fixup the remaining type accordingly.
3477 */
3478 NODE *
cxcast(NODE * p1,NODE * p2)3479 cxcast(NODE *p1, NODE *p2)
3480 {
3481 if (ANYCX(p1) && ANYCX(p2)) {
3482 if (p1->n_type != p2->n_type)
3483 p2 = mkcmplx(p2, p1->n_type);
3484 } else if (ANYCX(p1)) {
3485 p2 = mkcmplx(p2, strmemb(p1->n_ap)->stype);
3486 } else /* if (ANYCX(p2)) */ {
3487 p2 = cast(structref(p2, DOT, real), p1->n_type, 0);
3488 }
3489 nfree(p1);
3490 return p2;
3491 }
3492
3493 static void
cxargfixup(NODE * a,TWORD dt,struct attr * ap)3494 cxargfixup(NODE *a, TWORD dt, struct attr *ap)
3495 {
3496 NODE *p;
3497 TWORD t;
3498
3499 p = talloc();
3500 *p = *a;
3501 if (dt == STRTY) {
3502 /* dest complex */
3503 t = strmemb(ap)->stype;
3504 p = mkcmplx(p, t);
3505 } else {
3506 /* src complex, not dest */
3507 p = structref(p, DOT, ISFTY(dt) ? real : imag);
3508 }
3509 *a = *p;
3510 nfree(p);
3511 }
3512 #endif
3513