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