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