source: mainline/uspace/app/pcc/cc/ccom/pftn.c@ 92b42442

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 92b42442 was e6910c8, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 14 years ago

Update config.h and fix bug in ccom.

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