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