source: mainline/uspace/app/pcc/cc/ccom/pftn.c@ 0ffbed9

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

Added pcc source tree (contents of pcc-1.0.0.tgz)

  • 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 sz = ap->atypsz;
1143
1144#ifdef GCC_COMPAT
1145 if (ty == VOID)
1146 sz = SZCHAR;
1147#endif
1148 if (!ISSOU(BTYPE(ty))) {
1149 if (sz == 0) {
1150 uerror("unknown size");
1151 return(SZINT);
1152 }
1153 } else {
1154 if (talign(ty, apl) == 0)
1155 uerror("unknown structure/union/enum");
1156 }
1157
1158 return((unsigned int)sz * mult);
1159}
1160
1161/*
1162 * Save string (and print it out). If wide then wide string.
1163 */
1164NODE *
1165strend(int wide, char *str)
1166{
1167 struct symtab *sp;
1168 NODE *p;
1169
1170 /* If an identical string is already emitted, just forget this one */
1171 if (wide) {
1172 /* Do not save wide strings, at least not now */
1173 sp = getsymtab(str, SSTRING|STEMP);
1174 } else {
1175 str = addstring(str); /* enter string in string table */
1176 sp = lookup(str, SSTRING); /* check for existance */
1177 }
1178
1179 if (sp->soffset == 0) { /* No string */
1180 char *wr;
1181 int i;
1182
1183 sp->sclass = STATIC;
1184 sp->slevel = 1;
1185 sp->soffset = getlab();
1186 sp->squal = (CON >> TSHIFT);
1187 sp->sdf = permalloc(sizeof(union dimfun));
1188 if (wide) {
1189 sp->stype = WCHAR_TYPE+ARY;
1190 sp->sap = MKAP(WCHAR_TYPE);
1191 } else {
1192 if (funsigned_char) {
1193 sp->stype = UCHAR+ARY;
1194 sp->sap = MKAP(UCHAR);
1195 } else {
1196 sp->stype = CHAR+ARY;
1197 sp->sap = MKAP(CHAR);
1198 }
1199 }
1200 for (wr = sp->sname, i = 1; *wr; i++)
1201 if (*wr++ == '\\')
1202 (void)esccon(&wr);
1203
1204 sp->sdf->ddim = i;
1205 if (wide)
1206 inwstring(sp);
1207 else
1208 instring(sp);
1209 }
1210
1211 p = block(NAME, NIL, NIL, sp->stype, sp->sdf, sp->sap);
1212 p->n_sp = sp;
1213 return(clocal(p));
1214}
1215
1216/*
1217 * Print out a wide string by calling ninval().
1218 */
1219void
1220inwstring(struct symtab *sp)
1221{
1222 char *s = sp->sname;
1223 NODE *p;
1224
1225 defloc(sp);
1226 p = xbcon(0, NULL, WCHAR_TYPE);
1227 do {
1228 if (*s++ == '\\')
1229 p->n_lval = esccon(&s);
1230 else
1231 p->n_lval = (unsigned char)s[-1];
1232 ninval(0, (MKAP(WCHAR_TYPE))->atypsz, p);
1233 } while (s[-1] != 0);
1234 nfree(p);
1235}
1236
1237/*
1238 * update the offset pointed to by poff; return the
1239 * offset of a value of size `size', alignment `alignment',
1240 * given that off is increasing
1241 */
1242int
1243upoff(int size, int alignment, int *poff)
1244{
1245 int off;
1246
1247 off = *poff;
1248 SETOFF(off, alignment);
1249 if (off < 0)
1250 cerror("structure or stack overgrown"); /* wrapped */
1251 *poff = off+size;
1252 return (off);
1253}
1254
1255/*
1256 * allocate p with offset *poff, and update *poff
1257 */
1258int
1259oalloc(struct symtab *p, int *poff )
1260{
1261 int al, off, tsz;
1262 int noff;
1263
1264 /*
1265 * Only generate tempnodes if we are optimizing,
1266 * and only for integers, floats or pointers,
1267 * and not if the type on this level is volatile.
1268 */
1269 if (xtemps && ((p->sclass == AUTO) || (p->sclass == REGISTER)) &&
1270 (p->stype < STRTY || ISPTR(p->stype)) &&
1271 !(cqual(p->stype, p->squal) & VOL) && cisreg(p->stype)) {
1272 NODE *tn = tempnode(0, p->stype, p->sdf, p->sap);
1273 p->soffset = regno(tn);
1274 p->sflags |= STNODE;
1275 nfree(tn);
1276 return 0;
1277 }
1278
1279 al = talign(p->stype, p->sap);
1280 noff = off = *poff;
1281 tsz = (int)tsize(p->stype, p->sdf, p->sap);
1282#ifdef BACKAUTO
1283 if (p->sclass == AUTO) {
1284 noff = off + tsz;
1285 if (noff < 0)
1286 cerror("stack overflow");
1287 SETOFF(noff, al);
1288 off = -noff;
1289 } else
1290#endif
1291 if (p->sclass == PARAM && (p->stype == CHAR || p->stype == UCHAR ||
1292 p->stype == SHORT || p->stype == USHORT || p->stype == BOOL)) {
1293 off = upoff(SZINT, ALINT, &noff);
1294#ifndef RTOLBYTES
1295 off = noff - tsz;
1296#endif
1297 } else {
1298 off = upoff(tsz, al, &noff);
1299 }
1300
1301 if (p->sclass != REGISTER) {
1302 /* in case we are allocating stack space for register arguments */
1303 if (p->soffset == NOOFFSET)
1304 p->soffset = off;
1305 else if(off != p->soffset)
1306 return(1);
1307 }
1308
1309 *poff = noff;
1310 return(0);
1311}
1312
1313/*
1314 * Delay emission of code generated in argument headers.
1315 */
1316static void
1317edelay(NODE *p)
1318{
1319 if (blevel == 1) {
1320 /* Delay until after declarations */
1321 if (parlink == NULL)
1322 parlink = p;
1323 else
1324 parlink = block(COMOP, parlink, p, 0, 0, 0);
1325 } else
1326 ecomp(p);
1327}
1328
1329/*
1330 * Traverse through the array args, evaluate them and put the
1331 * resulting temp numbers in the dim fields.
1332 */
1333static void
1334evalidx(struct symtab *sp)
1335{
1336 union dimfun *df;
1337 NODE *p;
1338 TWORD t;
1339 int astkp = 0;
1340
1341 if (arrstk[0] == NIL)
1342 astkp++; /* for parameter arrays */
1343
1344 if (isdyn(sp))
1345 sp->sflags |= SDYNARRAY;
1346
1347 df = sp->sdf;
1348 for (t = sp->stype; t > BTMASK; t = DECREF(t)) {
1349 if (!ISARY(t))
1350 continue;
1351 if (df->ddim == -1) {
1352 p = tempnode(0, INT, 0, MKAP(INT));
1353 df->ddim = -regno(p);
1354 edelay(buildtree(ASSIGN, p, arrstk[astkp++]));
1355 }
1356 df++;
1357 }
1358 arrstkp = 0;
1359}
1360
1361/*
1362 * Return 1 if dynamic array, 0 otherwise.
1363 */
1364int
1365isdyn(struct symtab *sp)
1366{
1367 union dimfun *df = sp->sdf;
1368 TWORD t;
1369
1370 for (t = sp->stype; t > BTMASK; t = DECREF(t)) {
1371 if (!ISARY(t))
1372 return 0;
1373 if (df->ddim < 0 && df->ddim != NOOFFSET)
1374 return 1;
1375 df++;
1376 }
1377 return 0;
1378}
1379
1380/*
1381 * Allocate space on the stack for dynamic arrays (or at least keep track
1382 * of the index).
1383 * Strategy is as follows:
1384 * - first entry is a pointer to the dynamic datatype.
1385 * - if it's a one-dimensional array this will be the only entry used.
1386 * - if it's a multi-dimensional array the following (numdim-1) integers
1387 * will contain the sizes to multiply the indexes with.
1388 * - code to write the dimension sizes this will be generated here.
1389 * - code to allocate space on the stack will be generated here.
1390 */
1391static void
1392dynalloc(struct symtab *p, int *poff)
1393{
1394 union dimfun *df;
1395 NODE *n, *tn, *pol;
1396 TWORD t;
1397
1398 /*
1399 * The pointer to the array is not necessarily stored in a
1400 * TEMP node, but if it is, its number is in the soffset field;
1401 */
1402 t = p->stype;
1403 p->sflags |= STNODE;
1404 p->stype = INCREF(p->stype); /* Make this an indirect pointer */
1405 tn = tempnode(0, p->stype, p->sdf, p->sap);
1406 p->soffset = regno(tn);
1407
1408 df = p->sdf;
1409
1410 pol = bcon(1);
1411 for (; t > BTMASK; t = DECREF(t)) {
1412 if (!ISARY(t))
1413 break;
1414 if (df->ddim < 0)
1415 n = tempnode(-df->ddim, INT, 0, MKAP(INT));
1416 else
1417 n = bcon(df->ddim);
1418
1419 pol = buildtree(MUL, pol, n);
1420 df++;
1421 }
1422 /* Create stack gap */
1423 spalloc(tn, pol, tsize(t, 0, p->sap));
1424}
1425
1426/*
1427 * allocate a field of width w
1428 * new is 0 if new entry, 1 if redefinition, -1 if alignment
1429 */
1430int
1431falloc(struct symtab *p, int w, NODE *pty)
1432{
1433 int al,sz,type;
1434
1435 type = p ? p->stype : pty->n_type;
1436
1437 if (type == BOOL)
1438 type = BOOL_TYPE;
1439 if (type < CHAR || type > ULONGLONG) {
1440 uerror("illegal field type");
1441 type = INT;
1442 }
1443
1444 al = btattr[type].aalign;
1445 sz = btattr[type].atypsz;
1446
1447 if (w > sz) {
1448 uerror("field too big");
1449 w = sz;
1450 }
1451
1452 if (w == 0) { /* align only */
1453 SETOFF(rpole->rstr, al);
1454 if (p != NULL)
1455 uerror("zero size field");
1456 return(0);
1457 }
1458
1459 if (rpole->rstr%al + w > sz)
1460 SETOFF(rpole->rstr, al);
1461 if (p == NULL) {
1462 rpole->rstr += w; /* we know it will fit */
1463 return(0);
1464 }
1465
1466 /* establish the field */
1467
1468 p->soffset = rpole->rstr;
1469 rpole->rstr += w;
1470 p->stype = type;
1471 fldty(p);
1472 return(0);
1473}
1474
1475/*
1476 * handle unitialized declarations assumed to be not functions:
1477 * int a;
1478 * extern int a;
1479 * static int a;
1480 */
1481void
1482nidcl(NODE *p, int class)
1483{
1484 struct symtab *sp;
1485 int commflag = 0;
1486
1487 /* compute class */
1488 if (class == SNULL) {
1489 if (blevel > 1)
1490 class = AUTO;
1491 else if (blevel != 0 || rpole)
1492 cerror( "nidcl error" );
1493 else /* blevel = 0 */
1494 commflag = 1, class = EXTERN;
1495 }
1496
1497 defid(p, class);
1498
1499#ifdef GCC_COMPAT
1500 if (p->n_op == CM)
1501 cerror("nidcl CM");
1502#endif
1503
1504 sp = p->n_sp;
1505 /* check if forward decl */
1506 if (ISARY(sp->stype) && sp->sdf->ddim == NOOFFSET)
1507 return;
1508
1509 if (sp->sflags & SASG)
1510 return; /* already initialized */
1511
1512 switch (class) {
1513 case EXTDEF:
1514 /* simulate initialization by 0 */
1515 simpleinit(p->n_sp, bcon(0));
1516 break;
1517 case EXTERN:
1518 if (commflag)
1519 lcommadd(p->n_sp);
1520 else
1521 extdec(p->n_sp);
1522 break;
1523 case STATIC:
1524 if (blevel == 0)
1525 lcommadd(p->n_sp);
1526 else
1527 defzero(p->n_sp);
1528 break;
1529 }
1530}
1531
1532struct lcd {
1533 SLIST_ENTRY(lcd) next;
1534 struct symtab *sp;
1535};
1536
1537static SLIST_HEAD(, lcd) lhead = { NULL, &lhead.q_forw};
1538
1539/*
1540 * Add a local common statement to the printout list.
1541 */
1542void
1543lcommadd(struct symtab *sp)
1544{
1545 struct lcd *lc, *lcp;
1546
1547 lcp = NULL;
1548 SLIST_FOREACH(lc, &lhead, next) {
1549 if (lc->sp == sp)
1550 return; /* already exists */
1551 if (lc->sp == NULL && lcp == NULL)
1552 lcp = lc;
1553 }
1554 if (lcp == NULL) {
1555 lc = permalloc(sizeof(struct lcd));
1556 lc->sp = sp;
1557 SLIST_INSERT_LAST(&lhead, lc, next);
1558 } else
1559 lcp->sp = sp;
1560}
1561
1562/*
1563 * Delete a local common statement.
1564 */
1565void
1566lcommdel(struct symtab *sp)
1567{
1568 struct lcd *lc;
1569
1570 SLIST_FOREACH(lc, &lhead, next) {
1571 if (lc->sp == sp) {
1572 lc->sp = NULL;
1573 return;
1574 }
1575 }
1576}
1577
1578/*
1579 * Print out the remaining common statements.
1580 */
1581void
1582lcommprint(void)
1583{
1584 struct lcd *lc;
1585
1586 SLIST_FOREACH(lc, &lhead, next) {
1587 if (lc->sp != NULL)
1588 defzero(lc->sp);
1589 }
1590}
1591
1592/*
1593 * Merge given types to a single node.
1594 * Any type can end up here.
1595 * p is the old node, q is the old (if any).
1596 * CLASS is AUTO, EXTERN, REGISTER, STATIC or TYPEDEF.
1597 * QUALIFIER is VOL or CON
1598 * TYPE is CHAR, SHORT, INT, LONG, SIGNED, UNSIGNED, VOID, BOOL, FLOAT,
1599 * DOUBLE, STRTY, UNIONTY.
1600 */
1601struct typctx {
1602 int class, qual, sig, uns, cmplx, imag, err;
1603 TWORD type;
1604 NODE *saved;
1605 struct attr *pre, *post;
1606};
1607
1608static void
1609typwalk(NODE *p, void *arg)
1610{
1611 struct typctx *tc = arg;
1612
1613#define cmop(x,y) block(CM, x, y, INT, 0, MKAP(INT))
1614 switch (p->n_op) {
1615 case ATTRIB:
1616 if (tc->saved && (tc->saved->n_qual & 1)) {
1617 tc->post = attr_add(tc->post,gcc_attr_parse(p->n_left));
1618 } else {
1619 tc->pre = attr_add(tc->pre, gcc_attr_parse(p->n_left));
1620 }
1621 p->n_left = bcon(0); /* For tfree() */
1622 break;
1623 case CLASS:
1624 if (tc->class)
1625 tc->err = 1; /* max 1 class */
1626 tc->class = p->n_type;
1627 break;
1628
1629 case QUALIFIER:
1630#if 0
1631 if (p->n_qual == 0)
1632 uerror("invalid use of 'restrict'");
1633#endif
1634 tc->qual |= p->n_qual >> TSHIFT;
1635 break;
1636
1637 case TYPE:
1638 if (p->n_sp != NULL || ISSOU(p->n_type)) {
1639 /* typedef, enum or struct/union */
1640 if (tc->saved || tc->type)
1641 tc->err = 1;
1642#ifdef GCC_COMPAT
1643 if (ISSOU(p->n_type) && p->n_left) {
1644 if (tc->post)
1645 cerror("typwalk");
1646 tc->post = gcc_attr_parse(p->n_left);
1647 }
1648#endif
1649 tc->saved = ccopy(p);
1650 break;
1651 }
1652
1653 switch (p->n_type) {
1654 case BOOL:
1655 case CHAR:
1656 case FLOAT:
1657 case VOID:
1658 if (tc->type)
1659 tc->err = 1;
1660 tc->type = p->n_type;
1661 break;
1662 case DOUBLE:
1663 if (tc->type == 0)
1664 tc->type = DOUBLE;
1665 else if (tc->type == LONG)
1666 tc->type = LDOUBLE;
1667 else
1668 tc->err = 1;
1669 break;
1670 case SHORT:
1671 if (tc->type == 0 || tc->type == INT)
1672 tc->type = SHORT;
1673 else
1674 tc->err = 1;
1675 break;
1676 case INT:
1677 if (tc->type == SHORT || tc->type == LONG ||
1678 tc->type == LONGLONG)
1679 break;
1680 else if (tc->type == 0)
1681 tc->type = INT;
1682 else
1683 tc->err = 1;
1684 break;
1685 case LONG:
1686 if (tc->type == 0)
1687 tc->type = LONG;
1688 else if (tc->type == INT)
1689 break;
1690 else if (tc->type == LONG)
1691 tc->type = LONGLONG;
1692 else if (tc->type == DOUBLE)
1693 tc->type = LDOUBLE;
1694 else
1695 tc->err = 1;
1696 break;
1697 case SIGNED:
1698 if (tc->sig || tc->uns)
1699 tc->err = 1;
1700 tc->sig = 1;
1701 break;
1702 case UNSIGNED:
1703 if (tc->sig || tc->uns)
1704 tc->err = 1;
1705 tc->uns = 1;
1706 break;
1707 case COMPLEX:
1708 tc->cmplx = 1;
1709 break;
1710 case IMAG:
1711 tc->imag = 1;
1712 break;
1713 default:
1714 cerror("typwalk");
1715 }
1716 }
1717
1718}
1719
1720NODE *
1721typenode(NODE *p)
1722{
1723 struct symtab *sp;
1724 struct typctx tc;
1725 NODE *q;
1726 char *c;
1727
1728 memset(&tc, 0, sizeof(struct typctx));
1729
1730 flist(p, typwalk, &tc);
1731 tfree(p);
1732
1733 if (tc.err)
1734 goto bad;
1735
1736 if (tc.cmplx || tc.imag) {
1737 if (tc.type == 0)
1738 tc.type = DOUBLE;
1739 if ((tc.cmplx && tc.imag) || tc.sig || tc.uns ||
1740 !ISFTY(tc.type))
1741 goto bad;
1742 if (tc.cmplx) {
1743 c = tc.type == DOUBLE ? "0d" :
1744 tc.type == FLOAT ? "0f" : "0l";
1745 sp = lookup(addname(c), 0);
1746 tc.type = STRTY;
1747 tc.saved = mkty(tc.type, sp->sdf, sp->sap);
1748 tc.saved->n_sp = sp;
1749 tc.type = 0;
1750 } else
1751 tc.type += (FIMAG-FLOAT);
1752 }
1753
1754 if (tc.saved && tc.type)
1755 goto bad;
1756 if (tc.sig || tc.uns) {
1757 if (tc.type == 0)
1758 tc.type = tc.sig ? INT : UNSIGNED;
1759 if (tc.type > ULONGLONG)
1760 goto bad;
1761 if (tc.uns)
1762 tc.type = ENUNSIGN(tc.type);
1763 }
1764
1765 if (funsigned_char && tc.type == CHAR && tc.sig == 0)
1766 tc.type = UCHAR;
1767
1768#ifdef GCC_COMPAT
1769 if (pragma_packed) {
1770 q = bdty(CALL, bdty(NAME, "packed"), bcon(pragma_packed));
1771 tc.post = attr_add(tc.post, gcc_attr_parse(q));
1772 }
1773 if (pragma_aligned) {
1774 /* Deal with relevant pragmas */
1775 q = bdty(CALL, bdty(NAME, "aligned"), bcon(pragma_aligned));
1776 tc.post = attr_add(tc.post, gcc_attr_parse(q));
1777 }
1778 pragma_aligned = pragma_packed = 0;
1779#endif
1780 if ((q = tc.saved) == NULL) {
1781 TWORD t;
1782 if ((t = BTYPE(tc.type)) > LDOUBLE && t != VOID &&
1783 t != BOOL && !(t >= FIMAG && t <= LIMAG))
1784 cerror("typenode2 t %x", tc.type);
1785 if (t == UNDEF) {
1786 t = INT;
1787 MODTYPE(tc.type, INT);
1788 }
1789 q = mkty(tc.type, 0, MKAP(t));
1790 }
1791 q->n_ap = attr_add(q->n_ap, tc.post);
1792 q->n_qual = tc.qual;
1793 q->n_lval = tc.class;
1794#ifdef GCC_COMPAT
1795 if (tc.post) {
1796 /* Can only occur for TYPEDEF, STRUCT or UNION */
1797 if (tc.saved == NULL)
1798 cerror("typenode");
1799 }
1800 if (tc.pre)
1801 q->n_ap = attr_add(q->n_ap, tc.pre);
1802 gcc_tcattrfix(q);
1803#endif
1804 return q;
1805
1806bad: uerror("illegal type combination");
1807 return mkty(INT, 0, 0);
1808}
1809
1810struct tylnk {
1811 struct tylnk *next;
1812 union dimfun df;
1813};
1814
1815static void tyreduce(NODE *p, struct tylnk **, int *);
1816
1817static void
1818tylkadd(union dimfun dim, struct tylnk **tylkp, int *ntdim)
1819{
1820 (*tylkp)->next = tmpalloc(sizeof(struct tylnk));
1821 *tylkp = (*tylkp)->next;
1822 (*tylkp)->next = NULL;
1823 (*tylkp)->df = dim;
1824 (*ntdim)++;
1825}
1826
1827/*
1828 * merge type typ with identifier idp.
1829 * idp is returned as a NAME node with correct types,
1830 * typ is untouched since multiple declarations uses it.
1831 * typ has type attributes, idp can never carry such attributes
1832 * so on return just a pointer to the typ attributes is returned.
1833 */
1834NODE *
1835tymerge(NODE *typ, NODE *idp)
1836{
1837 TWORD t;
1838 NODE *p;
1839 union dimfun *j;
1840 struct tylnk *base, tylnk, *tylkp;
1841 struct attr *ap, *bap;
1842 int ntdim, i;
1843
1844#ifdef PCC_DEBUG
1845 if (ddebug > 2) {
1846 printf("tymerge(%p,%p)\n", typ, idp);
1847 fwalk(typ, eprint, 0);
1848 fwalk(idp, eprint, 0);
1849 }
1850#endif
1851
1852 if (typ->n_op == CM || idp->n_op == CM)
1853 cerror("tymerge CM");
1854
1855 if (typ->n_op != TYPE)
1856 cerror("tymerge: arg 1");
1857
1858 bap = typ->n_ap;
1859
1860 idp->n_type = typ->n_type;
1861 idp->n_qual |= typ->n_qual;
1862
1863 tylkp = &tylnk;
1864 tylkp->next = NULL;
1865 ntdim = 0;
1866
1867 tyreduce(idp, &tylkp, &ntdim);
1868
1869 for (t = typ->n_type, j = typ->n_df; t&TMASK; t = DECREF(t))
1870 if (ISARY(t) || ISFTN(t))
1871 tylkadd(*j++, &tylkp, &ntdim);
1872
1873 if (ntdim) {
1874 union dimfun *a = permalloc(sizeof(union dimfun) * ntdim);
1875 dimfuncnt += ntdim;
1876 for (i = 0, base = tylnk.next; base; base = base->next, i++)
1877 a[i] = base->df;
1878 idp->n_df = a;
1879 } else
1880 idp->n_df = NULL;
1881
1882 /* now idp is a single node: fix up type */
1883 if ((t = ctype(idp->n_type)) != idp->n_type) {
1884 idp->n_type = t;
1885 t = BTYPE(t);
1886 if (bap->atype == ATTR_BASETYP)
1887 bap = MKAP(t);
1888 else {
1889 for (ap = bap;
1890 ap->next->atype != ATTR_BASETYP; ap = ap->next)
1891 ;
1892 ap->next = MKAP(t);
1893 }
1894 }
1895
1896 if (idp->n_op != NAME) {
1897 for (p = idp->n_left; p->n_op != NAME; p = p->n_left)
1898 nfree(p);
1899 nfree(p);
1900 idp->n_op = NAME;
1901 }
1902 idp->n_ap = bap;
1903
1904 return(idp);
1905}
1906
1907/*
1908 * Retrieve all CM-separated argument types, sizes and dimensions and
1909 * put them in an array.
1910 * XXX - can only check first type level, side effects?
1911 */
1912static union arglist *
1913arglist(NODE *n)
1914{
1915 union arglist *al;
1916 NODE *w = n, **ap;
1917 int num, cnt, i, j, k;
1918 TWORD ty;
1919
1920#ifdef PCC_DEBUG
1921 if (pdebug) {
1922 printf("arglist %p\n", n);
1923 fwalk(n, eprint, 0);
1924 }
1925#endif
1926 /* First: how much to allocate */
1927 for (num = cnt = 0, w = n; w->n_op == CM; w = w->n_left) {
1928 cnt++; /* Number of levels */
1929 num++; /* At least one per step */
1930 if (w->n_right->n_op == ELLIPSIS)
1931 continue;
1932 ty = w->n_right->n_type;
1933 if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY)
1934 num++;
1935 while (ISFTN(ty) == 0 && ISARY(ty) == 0 && ty > BTMASK)
1936 ty = DECREF(ty);
1937 if (ty > BTMASK)
1938 num++;
1939 }
1940 cnt++;
1941 ty = w->n_type;
1942 if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY)
1943 num++;
1944 while (ISFTN(ty) == 0 && ISARY(ty) == 0 && ty > BTMASK)
1945 ty = DECREF(ty);
1946 if (ty > BTMASK)
1947 num++;
1948 num += 2; /* TEND + last arg type */
1949
1950 /* Second: Create list to work on */
1951 ap = tmpalloc(sizeof(NODE *) * cnt);
1952 al = permalloc(sizeof(union arglist) * num);
1953 arglistcnt += num;
1954
1955 for (w = n, i = 0; w->n_op == CM; w = w->n_left)
1956 ap[i++] = w->n_right;
1957 ap[i] = w;
1958
1959 /* Third: Create actual arg list */
1960 for (k = 0, j = i; j >= 0; j--) {
1961 if (ap[j]->n_op == ELLIPSIS) {
1962 al[k++].type = TELLIPSIS;
1963 ap[j]->n_op = ICON; /* for tfree() */
1964 continue;
1965 }
1966 /* Convert arrays to pointers */
1967 if (ISARY(ap[j]->n_type)) {
1968 ap[j]->n_type += (PTR-ARY);
1969 ap[j]->n_df++;
1970 }
1971 /* Convert (silently) functions to pointers */
1972 if (ISFTN(ap[j]->n_type))
1973 ap[j]->n_type = INCREF(ap[j]->n_type);
1974 ty = ap[j]->n_type;
1975#ifdef GCC_COMPAT
1976 if (ty == UNIONTY &&
1977 attr_find(ap[j]->n_ap, GCC_ATYP_TRANSP_UNION)){
1978 /* transparent unions must have compatible types
1979 * shortcut here: if pointers, set void *,
1980 * otherwise btype.
1981 */
1982 struct symtab *sp = strmemb(ap[j]->n_ap);
1983 ty = ISPTR(sp->stype) ? PTR|VOID : sp->stype;
1984 }
1985#endif
1986 al[k++].type = ty;
1987 if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY)
1988 al[k++].sap = ap[j]->n_ap;
1989 while (ISFTN(ty) == 0 && ISARY(ty) == 0 && ty > BTMASK)
1990 ty = DECREF(ty);
1991 if (ty > BTMASK)
1992 al[k++].df = ap[j]->n_df;
1993 }
1994 al[k++].type = TNULL;
1995 if (k > num)
1996 cerror("arglist: k%d > num%d", k, num);
1997 tfree(n);
1998#ifdef PCC_DEBUG
1999 if (pdebug)
2000 alprint(al, 0);
2001#endif
2002 return al;
2003}
2004
2005/*
2006 * build a type, and stash away dimensions,
2007 * from a parse tree of the declaration
2008 * the type is build top down, the dimensions bottom up
2009 */
2010void
2011tyreduce(NODE *p, struct tylnk **tylkp, int *ntdim)
2012{
2013 union dimfun dim;
2014 NODE *r = NULL;
2015 int o;
2016 TWORD t, q;
2017
2018 o = p->n_op;
2019 if (o == NAME) {
2020 p->n_qual = DECQAL(p->n_qual);
2021 return;
2022 }
2023
2024 t = INCREF(p->n_type);
2025 q = p->n_qual;
2026 switch (o) {
2027 case CALL:
2028 t += (FTN-PTR);
2029 dim.dfun = arglist(p->n_right);
2030 break;
2031 case UCALL:
2032 t += (FTN-PTR);
2033 dim.dfun = NULL;
2034 break;
2035 case LB:
2036 t += (ARY-PTR);
2037 if (p->n_right->n_op != ICON) {
2038 r = p->n_right;
2039 o = RB;
2040 } else {
2041 dim.ddim = (int)p->n_right->n_lval;
2042 nfree(p->n_right);
2043#ifdef notdef
2044 /* XXX - check dimensions at usage time */
2045 if (dim.ddim == NOOFFSET && p->n_left->n_op == LB)
2046 uerror("null dimension");
2047#endif
2048 }
2049 break;
2050 }
2051
2052 p->n_left->n_type = t;
2053 p->n_left->n_qual = INCQAL(q) | p->n_left->n_qual;
2054 tyreduce(p->n_left, tylkp, ntdim);
2055
2056 if (o == LB || o == (UCALL) || o == CALL)
2057 tylkadd(dim, tylkp, ntdim);
2058 if (o == RB) {
2059 dim.ddim = -1;
2060 tylkadd(dim, tylkp, ntdim);
2061 arrstk[arrstkp++] = r;
2062 }
2063
2064 p->n_sp = p->n_left->n_sp;
2065 p->n_type = p->n_left->n_type;
2066 p->n_qual = p->n_left->n_qual;
2067}
2068
2069static NODE *
2070argcast(NODE *p, TWORD t, union dimfun *d, struct attr *ap)
2071{
2072 NODE *u, *r = talloc();
2073
2074 r->n_op = NAME;
2075 r->n_type = t;
2076 r->n_qual = 0; /* XXX */
2077 r->n_df = d;
2078 r->n_ap = ap;
2079
2080 u = buildtree(CAST, r, p);
2081 nfree(u->n_left);
2082 r = u->n_right;
2083 nfree(u);
2084 return r;
2085}
2086
2087#ifdef PCC_DEBUG
2088/*
2089 * Print a prototype.
2090 */
2091static void
2092alprint(union arglist *al, int in)
2093{
2094 TWORD t;
2095 int i = 0, j;
2096
2097 for (; al->type != TNULL; al++) {
2098 for (j = in; j > 0; j--)
2099 printf(" ");
2100 printf("arg %d: ", i++);
2101 t = al->type;
2102 tprint(stdout, t, 0);
2103 while (t > BTMASK) {
2104 if (ISARY(t)) {
2105 al++;
2106 printf(" dim %d ", al->df->ddim);
2107 } else if (ISFTN(t)) {
2108 al++;
2109 alprint(al->df->dfun, in+1);
2110 }
2111 t = DECREF(t);
2112 }
2113 if (ISSOU(t)) {
2114 al++;
2115 struct attr *ap = attr_find(al->sap, ATTR_BASETYP);
2116 printf(" (size %d align %d)", ap->atypsz,
2117 ap->aalign);
2118 }
2119 printf("\n");
2120 }
2121 if (in == 0)
2122 printf("end arglist\n");
2123}
2124#endif
2125int
2126suemeq(struct attr *s1, struct attr *s2)
2127{
2128
2129 return (strmemb(s1) == strmemb(s2));
2130}
2131
2132/*
2133 * Sanity-check old-style args.
2134 */
2135static NODE *
2136oldarg(NODE *p)
2137{
2138 if (p->n_op == TYPE)
2139 uerror("type is not an argument");
2140 if (p->n_type == FLOAT)
2141 return cast(p, DOUBLE, p->n_qual);
2142 return p;
2143}
2144
2145/*
2146 * Do prototype checking and add conversions before calling a function.
2147 * Argument f is function and a is a CM-separated list of arguments.
2148 * Returns a merged node (via buildtree() of function and arguments.
2149 */
2150NODE *
2151doacall(struct symtab *sp, NODE *f, NODE *a)
2152{
2153 NODE *w, *r;
2154 union arglist *al;
2155 struct ap {
2156 struct ap *next;
2157 NODE *node;
2158 } *at, *apole = NULL;
2159 int argidx/* , hasarray = 0*/;
2160 TWORD type, arrt;
2161
2162#ifdef PCC_DEBUG
2163 if (ddebug) {
2164 printf("doacall.\n");
2165 fwalk(f, eprint, 0);
2166 if (a)
2167 fwalk(a, eprint, 0);
2168 }
2169#endif
2170
2171 /* First let MD code do something */
2172 calldec(f, a);
2173/* XXX XXX hack */
2174 if ((f->n_op == CALL) &&
2175 f->n_left->n_op == ADDROF &&
2176 f->n_left->n_left->n_op == NAME &&
2177 (f->n_left->n_left->n_type & 0x7e0) == 0x4c0)
2178 goto build;
2179/* XXX XXX hack */
2180
2181#ifndef NO_C_BUILTINS
2182 /* check for builtins. function pointers are not allowed */
2183 if (f->n_op == NAME &&
2184 f->n_sp->sname[0] == '_' && f->n_sp->sname[1] == '_')
2185 if ((w = builtin_check(f, a)) != NIL)
2186 return w;
2187#endif
2188
2189 /* Check for undefined or late defined enums */
2190 if (BTYPE(f->n_type) == ENUMTY) {
2191 /* not-yet check if declared enum */
2192 struct symtab *sq = strmemb(f->n_ap);
2193 if (sq->stype != ENUMTY)
2194 MODTYPE(f->n_type, sq->stype);
2195 if (BTYPE(f->n_type) == ENUMTY)
2196 uerror("enum %s not declared", sq->sname);
2197 }
2198
2199 /*
2200 * Do some basic checks.
2201 */
2202 if (f->n_df == NULL || (al = f->n_df[0].dfun) == NULL) {
2203 /*
2204 * Handle non-prototype declarations.
2205 */
2206 if (f->n_op == NAME && f->n_sp != NULL) {
2207 if (strncmp(f->n_sp->sname, "__builtin", 9) != 0)
2208 warner(Wmissing_prototypes, f->n_sp->sname);
2209 } else
2210 warner(Wmissing_prototypes, "<pointer>");
2211
2212 /* floats must be cast to double */
2213 if (a == NULL)
2214 goto build;
2215 if (a->n_op != CM) {
2216 a = oldarg(a);
2217 } else {
2218 for (w = a; w->n_left->n_op == CM; w = w->n_left)
2219 w->n_right = oldarg(w->n_right);
2220 w->n_left = oldarg(w->n_left);
2221 w->n_right = oldarg(w->n_right);
2222 }
2223 goto build;
2224 }
2225 if (al->type == VOID) {
2226 if (a != NULL)
2227 uerror("function takes no arguments");
2228 goto build; /* void function */
2229 } else {
2230 if (a == NULL) {
2231 uerror("function needs arguments");
2232 goto build;
2233 }
2234 }
2235#ifdef PCC_DEBUG
2236 if (pdebug) {
2237 printf("arglist for %s\n",
2238 f->n_sp != NULL ? f->n_sp->sname : "function pointer");
2239 alprint(al, 0);
2240 }
2241#endif
2242
2243 /*
2244 * Create a list of pointers to the nodes given as arg.
2245 */
2246 for (w = a; w->n_op == CM; w = w->n_left) {
2247 at = tmpalloc(sizeof(struct ap));
2248 at->node = w->n_right;
2249 at->next = apole;
2250 apole = at;
2251 }
2252 at = tmpalloc(sizeof(struct ap));
2253 at->node = w;
2254 at->next = apole;
2255 apole = at;
2256
2257 /*
2258 * Do the typechecking by walking up the list.
2259 */
2260 argidx = 1;
2261 while (al->type != TNULL) {
2262 if (al->type == TELLIPSIS) {
2263 /* convert the rest of float to double */
2264 for (; apole; apole = apole->next) {
2265 if (apole->node->n_type != FLOAT)
2266 continue;
2267 MKTY(apole->node, DOUBLE, 0, 0);
2268 }
2269 goto build;
2270 }
2271 if (apole == NULL) {
2272 uerror("too few arguments to function");
2273 goto build;
2274 }
2275/* al = prototyp, apole = argument till ftn */
2276/* type = argumentets typ, arrt = prototypens typ */
2277 type = apole->node->n_type;
2278 arrt = al->type;
2279#if 0
2280 if ((hasarray = ISARY(arrt)))
2281 arrt += (PTR-ARY);
2282#endif
2283 /* Taking addresses of arrays are meaningless in expressions */
2284 /* but people tend to do that and also use in prototypes */
2285 /* this is mostly a problem with typedefs */
2286 if (ISARY(type)) {
2287 if (ISPTR(arrt) && ISARY(DECREF(arrt)))
2288 type = INCREF(type);
2289 else
2290 type += (PTR-ARY);
2291 } else if (ISPTR(type) && !ISARY(DECREF(type)) &&
2292 ISPTR(arrt) && ISARY(DECREF(arrt))) {
2293 type += (ARY-PTR);
2294 type = INCREF(type);
2295 }
2296
2297 /* Check structs */
2298 if (type <= BTMASK && arrt <= BTMASK) {
2299 if (type != arrt) {
2300 if (ISSOU(BTYPE(type)) || ISSOU(BTYPE(arrt))) {
2301incomp: uerror("incompatible types for arg %d",
2302 argidx);
2303 } else {
2304 MKTY(apole->node, arrt, 0, 0)
2305 }
2306#ifndef NO_COMPLEX
2307 } else if (type == STRTY &&
2308 attr_find(apole->node->n_ap, ATTR_COMPLEX) &&
2309 attr_find(al[1].sap, ATTR_COMPLEX)) {
2310 /* Both are complex */
2311 if (strmemb(apole->node->n_ap)->stype !=
2312 strmemb(al[1].sap)->stype) {
2313 /* must convert to correct type */
2314 w = talloc();
2315 *w = *apole->node;
2316 w = mkcmplx(w,
2317 strmemb(al[1].sap)->stype);
2318 *apole->node = *w;
2319 nfree(w);
2320 }
2321 goto out;
2322#endif
2323 } else if (ISSOU(BTYPE(type))) {
2324 if (!suemeq(apole->node->n_ap, al[1].sap))
2325 goto incomp;
2326 }
2327 goto out;
2328 }
2329
2330 /* XXX should (recusively) check return type and arg list of
2331 func ptr arg XXX */
2332 if (ISFTN(DECREF(arrt)) && ISFTN(type))
2333 type = INCREF(type);
2334
2335 /* Hereafter its only pointers (or arrays) left */
2336 /* Check for struct/union intermixing with other types */
2337 if (((type <= BTMASK) && ISSOU(BTYPE(type))) ||
2338 ((arrt <= BTMASK) && ISSOU(BTYPE(arrt))))
2339 goto incomp;
2340
2341 /* Check for struct/union compatibility */
2342 if (type == arrt) {
2343 if (ISSOU(BTYPE(type))) {
2344 if (suemeq(apole->node->n_ap, al[1].sap))
2345 goto out;
2346 } else
2347 goto out;
2348 }
2349 if (BTYPE(arrt) == VOID && type > BTMASK)
2350 goto skip; /* void *f = some pointer */
2351 if (arrt > BTMASK && BTYPE(type) == VOID)
2352 goto skip; /* some *f = void pointer */
2353 if (apole->node->n_op == ICON && apole->node->n_lval == 0)
2354 goto skip; /* Anything assigned a zero */
2355
2356 if ((type & ~BTMASK) == (arrt & ~BTMASK)) {
2357 /* do not complain for pointers with signedness */
2358 if ((DEUNSIGN(BTYPE(type)) == DEUNSIGN(BTYPE(arrt))) &&
2359 (BTYPE(type) != BTYPE(arrt))) {
2360 warner(Wpointer_sign, NULL);
2361 goto skip;
2362 }
2363 }
2364
2365 werror("implicit conversion of argument %d due to prototype",
2366 argidx);
2367
2368skip: if (ISSOU(BTYPE(arrt))) {
2369 MKTY(apole->node, arrt, 0, al[1].sap)
2370 } else {
2371 MKTY(apole->node, arrt, 0, MKAP(BTYPE(arrt)))
2372 }
2373
2374out: al++;
2375 if (ISSOU(BTYPE(arrt)))
2376 al++;
2377#if 0
2378 while (arrt > BTMASK && !ISFTN(arrt))
2379 arrt = DECREF(arrt);
2380 if (ISFTN(arrt) || hasarray)
2381 al++;
2382#else
2383 while (arrt > BTMASK) {
2384 if (ISARY(arrt) || ISFTN(arrt)) {
2385 al++;
2386 break;
2387 }
2388 arrt = DECREF(arrt);
2389 }
2390#endif
2391 apole = apole->next;
2392 argidx++;
2393 }
2394 if (apole != NULL)
2395 uerror("too many arguments to function");
2396
2397build: if (sp != NULL && (sp->sflags & SINLINE) && (w = inlinetree(sp, f, a)))
2398 return w;
2399 return buildtree(a == NIL ? UCALL : CALL, f, a);
2400}
2401
2402static int
2403chk2(TWORD type, union dimfun *dsym, union dimfun *ddef)
2404{
2405 while (type > BTMASK) {
2406 switch (type & TMASK) {
2407 case ARY:
2408 /* may be declared without dimension */
2409 if (dsym->ddim == NOOFFSET)
2410 dsym->ddim = ddef->ddim;
2411 if (dsym->ddim < 0 && ddef->ddim < 0)
2412 ; /* dynamic arrays as arguments */
2413 else if (ddef->ddim > 0 && dsym->ddim != ddef->ddim)
2414 return 1;
2415 dsym++, ddef++;
2416 break;
2417 case FTN:
2418 /* old-style function headers with function pointers
2419 * will most likely not have a prototype.
2420 * This is not considered an error. */
2421 if (ddef->dfun == NULL) {
2422#ifdef notyet
2423 werror("declaration not a prototype");
2424#endif
2425 } else if (chkftn(dsym->dfun, ddef->dfun))
2426 return 1;
2427 dsym++, ddef++;
2428 break;
2429 }
2430 type = DECREF(type);
2431 }
2432 return 0;
2433}
2434
2435/*
2436 * Compare two function argument lists to see if they match.
2437 */
2438int
2439chkftn(union arglist *usym, union arglist *udef)
2440{
2441 TWORD t2;
2442 int ty, tyn;
2443
2444 if (usym == NULL)
2445 return 0;
2446 if (cftnsp != NULL && udef == NULL && usym->type == VOID)
2447 return 0; /* foo() { function with foo(void); prototype */
2448 if (udef == NULL && usym->type != TNULL)
2449 return 1;
2450 while (usym->type != TNULL) {
2451 if (usym->type == udef->type)
2452 goto done;
2453 /*
2454 * If an old-style declaration, then all types smaller than
2455 * int are given as int parameters.
2456 */
2457 if (intcompare) {
2458 ty = BTYPE(usym->type);
2459 tyn = BTYPE(udef->type);
2460 if (ty == tyn || ty != INT)
2461 return 1;
2462 if (tyn == CHAR || tyn == UCHAR ||
2463 tyn == SHORT || tyn == USHORT)
2464 goto done;
2465 return 1;
2466 } else
2467 return 1;
2468
2469done: ty = BTYPE(usym->type);
2470 t2 = usym->type;
2471 if (ISSOU(ty)) {
2472 usym++, udef++;
2473 if (suemeq(usym->sap, udef->sap) == 0)
2474 return 1;
2475 }
2476
2477 while (ISFTN(t2) == 0 && ISARY(t2) == 0 && t2 > BTMASK)
2478 t2 = DECREF(t2);
2479 if (t2 > BTMASK) {
2480 usym++, udef++;
2481 if (chk2(t2, usym->df, udef->df))
2482 return 1;
2483 }
2484 usym++, udef++;
2485 }
2486 if (usym->type != udef->type)
2487 return 1;
2488 return 0;
2489}
2490
2491void
2492fixtype(NODE *p, int class)
2493{
2494 unsigned int t, type;
2495 int mod1, mod2;
2496 /* fix up the types, and check for legality */
2497
2498 /* forward declared enums */
2499 if (BTYPE(p->n_sp->stype) == ENUMTY) {
2500 MODTYPE(p->n_sp->stype, strmemb(p->n_sp->sap)->stype);
2501 }
2502
2503 if( (type = p->n_type) == UNDEF ) return;
2504 if ((mod2 = (type&TMASK))) {
2505 t = DECREF(type);
2506 while( mod1=mod2, mod2 = (t&TMASK) ){
2507 if( mod1 == ARY && mod2 == FTN ){
2508 uerror( "array of functions is illegal" );
2509 type = 0;
2510 }
2511 else if( mod1 == FTN && ( mod2 == ARY || mod2 == FTN ) ){
2512 uerror( "function returns illegal type" );
2513 type = 0;
2514 }
2515 t = DECREF(t);
2516 }
2517 }
2518
2519 /* detect function arguments, watching out for structure declarations */
2520 if (rpole && ISFTN(type)) {
2521 uerror("function illegal in structure or union");
2522 type = INCREF(type);
2523 }
2524 p->n_type = type;
2525}
2526
2527/*
2528 * give undefined version of class
2529 */
2530int
2531uclass(int class)
2532{
2533 if (class == SNULL)
2534 return(EXTERN);
2535 else if (class == STATIC)
2536 return(USTATIC);
2537 else
2538 return(class);
2539}
2540
2541int
2542fixclass(int class, TWORD type)
2543{
2544 extern int fun_inline;
2545
2546 /* first, fix null class */
2547 if (class == SNULL) {
2548 if (fun_inline && ISFTN(type))
2549 return SNULL;
2550 if (rpole)
2551 class = rpole->rsou == STNAME ? MOS : MOU;
2552 else if (blevel == 0)
2553 class = EXTDEF;
2554 else
2555 class = AUTO;
2556 }
2557
2558 /* now, do general checking */
2559
2560 if( ISFTN( type ) ){
2561 switch( class ) {
2562 default:
2563 uerror( "function has illegal storage class" );
2564 case AUTO:
2565 class = EXTERN;
2566 case EXTERN:
2567 case EXTDEF:
2568 case TYPEDEF:
2569 case STATIC:
2570 case USTATIC:
2571 ;
2572 }
2573 }
2574
2575 if (class & FIELD) {
2576 if (rpole && rpole->rsou != STNAME && rpole->rsou != UNAME)
2577 uerror("illegal use of field");
2578 return(class);
2579 }
2580
2581 switch (class) {
2582
2583 case MOS:
2584 case MOU:
2585 if (rpole == NULL)
2586 uerror("illegal member class");
2587 return(class);
2588
2589 case REGISTER:
2590 if (blevel == 0)
2591 uerror("illegal register declaration");
2592 if (blevel == 1)
2593 return(PARAM);
2594 else
2595 return(AUTO);
2596
2597 case AUTO:
2598 if( blevel < 2 ) uerror( "illegal ULABEL class" );
2599 return( class );
2600
2601 case EXTERN:
2602 case STATIC:
2603 case EXTDEF:
2604 case TYPEDEF:
2605 case USTATIC:
2606 case PARAM:
2607 return( class );
2608
2609 default:
2610 cerror( "illegal class: %d", class );
2611 /* NOTREACHED */
2612
2613 }
2614 return 0; /* XXX */
2615}
2616
2617/*
2618 * Generates a goto statement; sets up label number etc.
2619 */
2620void
2621gotolabel(char *name)
2622{
2623 struct symtab *s = lookup(name, SLBLNAME);
2624
2625 if (s->soffset == 0)
2626 s->soffset = -getlab();
2627 branch(s->soffset < 0 ? -s->soffset : s->soffset);
2628}
2629
2630/*
2631 * Sets a label for gotos.
2632 */
2633void
2634deflabel(char *name, NODE *p)
2635{
2636 struct symtab *s = lookup(name, SLBLNAME);
2637
2638 s->sap = gcc_attr_parse(p);
2639 if (s->soffset > 0)
2640 uerror("label '%s' redefined", name);
2641 if (s->soffset == 0)
2642 s->soffset = getlab();
2643 if (s->soffset < 0)
2644 s->soffset = -s->soffset;
2645 plabel( s->soffset);
2646}
2647
2648struct symtab *
2649getsymtab(char *name, int flags)
2650{
2651 struct symtab *s;
2652
2653 if (flags & STEMP) {
2654 s = tmpalloc(sizeof(struct symtab));
2655 } else {
2656 s = permalloc(sizeof(struct symtab));
2657 symtabcnt++;
2658 }
2659 s->sname = name;
2660 s->soname = NULL;
2661 s->snext = NULL;
2662 s->stype = UNDEF;
2663 s->squal = 0;
2664 s->sclass = SNULL;
2665 s->sflags = (short)(flags & SMASK);
2666 s->soffset = 0;
2667 s->slevel = (char)blevel;
2668 s->sdf = NULL;
2669 s->sap = NULL;
2670 return s;
2671}
2672
2673int
2674fldchk(int sz)
2675{
2676 if (rpole->rsou != STNAME && rpole->rsou != UNAME)
2677 uerror("field outside of structure");
2678 if (sz < 0 || sz >= FIELD) {
2679 uerror("illegal field size");
2680 return 1;
2681 }
2682 return 0;
2683}
2684
2685#ifdef PCC_DEBUG
2686static char *
2687ccnames[] = { /* names of storage classes */
2688 "SNULL",
2689 "AUTO",
2690 "EXTERN",
2691 "STATIC",
2692 "REGISTER",
2693 "EXTDEF",
2694 "LABEL",
2695 "ULABEL",
2696 "MOS",
2697 "PARAM",
2698 "STNAME",
2699 "MOU",
2700 "UNAME",
2701 "TYPEDEF",
2702 "FORTRAN",
2703 "ENAME",
2704 "MOE",
2705 "UFORTRAN",
2706 "USTATIC",
2707 };
2708
2709char *
2710scnames(int c)
2711{
2712 /* return the name for storage class c */
2713 static char buf[12];
2714 if( c&FIELD ){
2715 snprintf( buf, sizeof(buf), "FIELD[%d]", c&FLDSIZ );
2716 return( buf );
2717 }
2718 return( ccnames[c] );
2719 }
2720#endif
2721
2722static char *stack_chk_fail = "__stack_chk_fail";
2723static char *stack_chk_guard = "__stack_chk_guard";
2724static char *stack_chk_canary = "__stack_chk_canary";
2725
2726void
2727sspinit()
2728{
2729 NODE *p;
2730
2731 p = block(NAME, NIL, NIL, FTN+VOID, 0, MKAP(VOID));
2732 p->n_sp = lookup(stack_chk_fail, SNORMAL);
2733 defid(p, EXTERN);
2734 nfree(p);
2735
2736 p = block(NAME, NIL, NIL, INT, 0, MKAP(INT));
2737 p->n_sp = lookup(stack_chk_guard, SNORMAL);
2738 defid(p, EXTERN);
2739 nfree(p);
2740}
2741
2742void
2743sspstart()
2744{
2745 NODE *p, *q;
2746
2747 q = block(NAME, NIL, NIL, INT, 0, MKAP(INT));
2748 q->n_sp = lookup(stack_chk_guard, SNORMAL);
2749 q = clocal(q);
2750
2751 p = block(REG, NIL, NIL, INT, 0, 0);
2752 p->n_lval = 0;
2753 p->n_rval = FPREG;
2754 q = block(ER, p, q, INT, 0, MKAP(INT));
2755 q = clocal(q);
2756
2757 p = block(NAME, NIL, NIL, INT, 0, MKAP(INT));
2758 p->n_qual = VOL >> TSHIFT;
2759 p->n_sp = lookup(stack_chk_canary, SNORMAL);
2760 defid(p, AUTO);
2761 p = clocal(p);
2762 ecomp(buildtree(ASSIGN, p, q));
2763}
2764
2765void
2766sspend()
2767{
2768 NODE *p, *q;
2769 TWORD t;
2770 int lab;
2771
2772 if (retlab != NOLAB) {
2773 plabel(retlab);
2774 retlab = getlab();
2775 }
2776
2777 t = DECREF(cftnsp->stype);
2778 if (t == BOOL)
2779 t = BOOL_TYPE;
2780
2781 p = block(NAME, NIL, NIL, INT, 0, MKAP(INT));
2782 p->n_sp = lookup(stack_chk_canary, SNORMAL);
2783 p = clocal(p);
2784
2785 q = block(REG, NIL, NIL, INT, 0, 0);
2786 q->n_lval = 0;
2787 q->n_rval = FPREG;
2788 q = block(ER, p, q, INT, 0, MKAP(INT));
2789
2790 p = block(NAME, NIL, NIL, INT, 0, MKAP(INT));
2791 p->n_sp = lookup(stack_chk_guard, SNORMAL);
2792 p = clocal(p);
2793
2794 lab = getlab();
2795 cbranch(buildtree(EQ, p, q), bcon(lab));
2796
2797 p = block(NAME, NIL, NIL, FTN+VOID, 0, MKAP(VOID));
2798 p->n_sp = lookup(stack_chk_fail, SNORMAL);
2799 p = clocal(p);
2800
2801 ecomp(buildtree(UCALL, p, NIL));
2802
2803 plabel(lab);
2804}
2805
2806/*
2807 * Allocate on the permanent heap for inlines, otherwise temporary heap.
2808 */
2809void *
2810blkalloc(int size)
2811{
2812 return isinlining || blevel < 2 ? permalloc(size) : tmpalloc(size);
2813}
2814
2815/*
2816 * Allocate on the permanent heap for inlines, otherwise temporary heap.
2817 */
2818void *
2819inlalloc(int size)
2820{
2821 return isinlining ? permalloc(size) : tmpalloc(size);
2822}
2823
2824struct attr *
2825attr_new(int type, int nelem)
2826{
2827 struct attr *ap;
2828 int sz;
2829
2830 sz = sizeof(struct attr) + nelem * sizeof(union aarg);
2831
2832 ap = memset(blkalloc(sz), 0, sz);
2833 ap->atype = type;
2834 return ap;
2835}
2836
2837/*
2838 * Add attribute list new before old and return new.
2839 */
2840struct attr *
2841attr_add(struct attr *old, struct attr *new)
2842{
2843 struct attr *ap;
2844
2845 if (new == NULL)
2846 return old; /* nothing to add */
2847
2848 for (ap = new; ap->next; ap = ap->next)
2849 ;
2850 ap->next = old;
2851 return new;
2852}
2853
2854/*
2855 * Search for attribute type in list ap. Return entry or NULL.
2856 */
2857struct attr *
2858attr_find(struct attr *ap, int type)
2859{
2860
2861 for (; ap && ap->atype != type; ap = ap->next)
2862 ;
2863 return ap;
2864}
2865
2866/*
2867 * Copy an attribute struct.
2868 * Return destination.
2869 */
2870struct attr *
2871attr_copy(struct attr *aps, struct attr *apd, int n)
2872{
2873 int sz = sizeof(struct attr) + n * sizeof(union aarg);
2874 return memcpy(apd, aps, sz);
2875}
2876
2877/*
2878 * Duplicate an attribute, like strdup.
2879 */
2880struct attr *
2881attr_dup(struct attr *ap, int n)
2882{
2883 int sz = sizeof(struct attr) + n * sizeof(union aarg);
2884 ap = memcpy(blkalloc(sz), ap, sz);
2885 ap->next = NULL;
2886 return ap;
2887}
2888
2889/*
2890 * Fetch pointer to first member in a struct list.
2891 */
2892struct symtab *
2893strmemb(struct attr *ap)
2894{
2895
2896 if ((ap = attr_find(ap, ATTR_STRUCT)) == NULL)
2897 cerror("strmemb");
2898 return ap->amlist;
2899}
2900
2901#ifndef NO_COMPLEX
2902
2903static char *real, *imag;
2904static struct symtab *cxsp[3];
2905/*
2906 * As complex numbers internally are handled as structs, create
2907 * these by hand-crafting them.
2908 */
2909void
2910complinit()
2911{
2912 struct attr *ap;
2913 struct rstack *rp;
2914 NODE *p, *q;
2915 char *n[] = { "0f", "0d", "0l" };
2916 int i, odebug;
2917
2918 odebug = ddebug;
2919 ddebug = 0;
2920 real = addname("__real");
2921 imag = addname("__imag");
2922 p = block(NAME, NIL, NIL, FLOAT, 0, MKAP(FLOAT));
2923 for (i = 0; i < 3; i++) {
2924 p->n_type = FLOAT+i;
2925 p->n_ap = MKAP(FLOAT+i);
2926 rpole = rp = bstruct(NULL, STNAME, NULL);
2927 soumemb(p, real, 0);
2928 soumemb(p, imag, 0);
2929 q = dclstruct(rp);
2930 cxsp[i] = q->n_sp = lookup(addname(n[i]), 0);
2931 defid(q, TYPEDEF);
2932 ap = attr_new(ATTR_COMPLEX, 0);
2933 q->n_sp->sap = attr_add(q->n_sp->sap, ap);
2934 nfree(q);
2935 }
2936 nfree(p);
2937 ddebug = odebug;
2938}
2939
2940/*
2941 * Return the highest real floating point type.
2942 * Known that at least one type is complex or imaginary.
2943 */
2944static TWORD
2945maxtyp(NODE *l, NODE *r)
2946{
2947 TWORD tl, tr, t;
2948
2949 tl = ANYCX(l) ? strmemb(l->n_ap)->stype : l->n_type;
2950 tr = ANYCX(r) ? strmemb(r->n_ap)->stype : r->n_type;
2951 if (ISITY(tl))
2952 tl -= (FIMAG - FLOAT);
2953 if (ISITY(tr))
2954 tr -= (FIMAG - FLOAT);
2955 t = tl > tr ? tl : tr;
2956 if (!ISFTY(t))
2957 cerror("maxtyp");
2958 return t;
2959}
2960
2961/*
2962 * Fetch space on stack for complex struct.
2963 */
2964static NODE *
2965cxstore(TWORD t)
2966{
2967 struct symtab s;
2968
2969 s = *cxsp[t - FLOAT];
2970 s.sclass = AUTO;
2971 s.soffset = NOOFFSET;
2972 oalloc(&s, &autooff);
2973 return nametree(&s);
2974}
2975
2976#define comop(x,y) buildtree(COMOP, x, y)
2977
2978static NODE *
2979mkcmplx(NODE *p, TWORD dt)
2980{
2981 NODE *q, *r, *i, *t;
2982
2983 if (!ANYCX(p)) {
2984 /* Not complex, convert to complex on stack */
2985 q = cxstore(dt);
2986 if (ISITY(p->n_type)) {
2987 p->n_type = p->n_type - FIMAG + FLOAT;
2988 r = bcon(0);
2989 i = p;
2990 } else {
2991 r = p;
2992 i = bcon(0);
2993 }
2994 p = buildtree(ASSIGN, structref(ccopy(q), DOT, real), r);
2995 p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, imag), i));
2996 p = comop(p, q);
2997 } else {
2998 if (strmemb(p->n_ap)->stype != dt) {
2999 q = cxstore(dt);
3000 p = buildtree(ADDROF, p, NIL);
3001 t = tempnode(0, p->n_type, p->n_df, p->n_ap);
3002 p = buildtree(ASSIGN, ccopy(t), p);
3003 p = comop(p, buildtree(ASSIGN,
3004 structref(ccopy(q), DOT, real),
3005 structref(ccopy(t), STREF, real)));
3006 p = comop(p, buildtree(ASSIGN,
3007 structref(ccopy(q), DOT, imag),
3008 structref(t, STREF, imag)));
3009 p = comop(p, q);
3010 }
3011 }
3012 return p;
3013}
3014
3015static NODE *
3016cxasg(NODE *l, NODE *r)
3017{
3018 TWORD tl, tr;
3019
3020 tl = strattr(l->n_ap) ? strmemb(l->n_ap)->stype : 0;
3021 tr = strattr(r->n_ap) ? strmemb(r->n_ap)->stype : 0;
3022
3023 if (ANYCX(l) && ANYCX(r) && tl != tr) {
3024 /* different types in structs */
3025 r = mkcmplx(r, tl);
3026 } else if (!ANYCX(l))
3027 r = structref(r, DOT, ISITY(l->n_type) ? imag : real);
3028 else if (!ANYCX(r))
3029 r = mkcmplx(r, tl);
3030 return buildtree(ASSIGN, l, r);
3031}
3032
3033/*
3034 * Fixup complex operations.
3035 * At least one operand is complex.
3036 */
3037NODE *
3038cxop(int op, NODE *l, NODE *r)
3039{
3040 TWORD mxtyp;
3041 NODE *p, *q;
3042 NODE *ltemp, *rtemp;
3043 NODE *real_l, *imag_l;
3044 NODE *real_r, *imag_r;
3045
3046 if (op == ASSIGN)
3047 return cxasg(l, r);
3048
3049 mxtyp = maxtyp(l, r);
3050 l = mkcmplx(l, mxtyp);
3051 r = mkcmplx(r, mxtyp);
3052
3053
3054 /* put a pointer to left and right elements in a TEMP */
3055 l = buildtree(ADDROF, l, NIL);
3056 ltemp = tempnode(0, l->n_type, l->n_df, l->n_ap);
3057 l = buildtree(ASSIGN, ccopy(ltemp), l);
3058
3059 r = buildtree(ADDROF, r, NIL);
3060 rtemp = tempnode(0, r->n_type, r->n_df, r->n_ap);
3061 r = buildtree(ASSIGN, ccopy(rtemp), r);
3062
3063 p = comop(l, r);
3064
3065 /* create the four trees needed for calculation */
3066 real_l = structref(ccopy(ltemp), STREF, real);
3067 real_r = structref(ccopy(rtemp), STREF, real);
3068 imag_l = structref(ltemp, STREF, imag);
3069 imag_r = structref(rtemp, STREF, imag);
3070
3071 /* get storage on stack for the result */
3072 q = cxstore(mxtyp);
3073
3074 switch (op) {
3075 case NE:
3076 case EQ:
3077 tfree(q);
3078 p = buildtree(op, comop(p, real_l), real_r);
3079 q = buildtree(op, imag_l, imag_r);
3080 p = buildtree(op == EQ ? ANDAND : OROR, p, q);
3081 return p;
3082
3083 case PLUS:
3084 case MINUS:
3085 p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, real),
3086 buildtree(op, real_l, real_r)));
3087 p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, imag),
3088 buildtree(op, imag_l, imag_r)));
3089 break;
3090
3091 case MUL:
3092 /* Complex mul is "complex" */
3093 /* (u+iv)*(x+iy)=((u*x)-(v*y))+i(v*x+y*u) */
3094 p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, real),
3095 buildtree(MINUS,
3096 buildtree(MUL, ccopy(real_r), ccopy(real_l)),
3097 buildtree(MUL, ccopy(imag_r), ccopy(imag_l)))));
3098 p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, imag),
3099 buildtree(PLUS,
3100 buildtree(MUL, real_r, imag_l),
3101 buildtree(MUL, imag_r, real_l))));
3102 break;
3103
3104 case DIV:
3105 /* Complex div is even more "complex" */
3106 /* (u+iv)/(x+iy)=(u*x+v*y)/(x*x+y*y)+i((v*x-u*y)/(x*x+y*y)) */
3107 p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, real),
3108 buildtree(DIV,
3109 buildtree(PLUS,
3110 buildtree(MUL, ccopy(real_r), ccopy(real_l)),
3111 buildtree(MUL, ccopy(imag_r), ccopy(imag_l))),
3112 buildtree(PLUS,
3113 buildtree(MUL, ccopy(real_r), ccopy(real_r)),
3114 buildtree(MUL, ccopy(imag_r), ccopy(imag_r))))));
3115 p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, real),
3116 buildtree(DIV,
3117 buildtree(MINUS,
3118 buildtree(MUL, ccopy(imag_l), ccopy(real_r)),
3119 buildtree(MUL, ccopy(real_l), ccopy(imag_r))),
3120 buildtree(PLUS,
3121 buildtree(MUL, ccopy(real_r), ccopy(real_r)),
3122 buildtree(MUL, ccopy(imag_r), ccopy(imag_r))))));
3123 tfree(real_r);
3124 tfree(real_l);
3125 tfree(imag_r);
3126 tfree(imag_l);
3127 break;
3128 default:
3129 cerror("bad complex op %d", op);
3130 }
3131 return comop(p, q);
3132}
3133
3134/*
3135 * Fixup imaginary operations.
3136 * At least one operand is imaginary, none is complex.
3137 */
3138NODE *
3139imop(int op, NODE *l, NODE *r)
3140{
3141 NODE *p, *q;
3142 TWORD mxtyp;
3143 int li, ri;
3144
3145 li = ri = 0;
3146 if (ISITY(l->n_type))
3147 li = 1, l->n_type = l->n_type - (FIMAG-FLOAT);
3148 if (ISITY(r->n_type))
3149 ri = 1, r->n_type = r->n_type - (FIMAG-FLOAT);
3150
3151 mxtyp = maxtyp(l, r);
3152 switch (op) {
3153 case ASSIGN:
3154 /* if both are imag, store value, otherwise store 0.0 */
3155 if (!(li && ri)) {
3156 tfree(r);
3157 r = bcon(0);
3158 }
3159 p = buildtree(ASSIGN, l, r);
3160 p->n_type = p->n_type += (FIMAG-FLOAT);
3161 break;
3162
3163 case PLUS:
3164 if (li && ri) {
3165 p = buildtree(PLUS, l, r);
3166 p->n_type = p->n_type += (FIMAG-FLOAT);
3167 } else {
3168 /* If one is imaginary and one is real, make complex */
3169 if (li)
3170 q = l, l = r, r = q; /* switch */
3171 q = cxstore(mxtyp);
3172 p = buildtree(ASSIGN,
3173 structref(ccopy(q), DOT, real), l);
3174 p = comop(p, buildtree(ASSIGN,
3175 structref(ccopy(q), DOT, imag), r));
3176 p = comop(p, q);
3177 }
3178 break;
3179
3180 case MINUS:
3181 if (li && ri) {
3182 p = buildtree(MINUS, l, r);
3183 p->n_type = p->n_type += (FIMAG-FLOAT);
3184 } else if (li) {
3185 q = cxstore(mxtyp);
3186 p = buildtree(ASSIGN, structref(ccopy(q), DOT, real),
3187 buildtree(UMINUS, r, NIL));
3188 p = comop(p, buildtree(ASSIGN,
3189 structref(ccopy(q), DOT, imag), l));
3190 p = comop(p, q);
3191 } else /* if (ri) */ {
3192 q = cxstore(mxtyp);
3193 p = buildtree(ASSIGN,
3194 structref(ccopy(q), DOT, real), l);
3195 p = comop(p, buildtree(ASSIGN,
3196 structref(ccopy(q), DOT, imag),
3197 buildtree(UMINUS, r, NIL)));
3198 p = comop(p, q);
3199 }
3200 break;
3201
3202 case MUL:
3203 p = buildtree(MUL, l, r);
3204 if (li && ri)
3205 p = buildtree(UMINUS, p, NIL);
3206 if (li ^ ri)
3207 p->n_type = p->n_type += (FIMAG-FLOAT);
3208 break;
3209
3210 case DIV:
3211 p = buildtree(DIV, l, r);
3212 if (ri && !li)
3213 p = buildtree(UMINUS, p, NIL);
3214 if (li ^ ri)
3215 p->n_type = p->n_type += (FIMAG-FLOAT);
3216 break;
3217 default:
3218 cerror("imop");
3219 p = NULL;
3220 }
3221 return p;
3222}
3223
3224NODE *
3225cxelem(int op, NODE *p)
3226{
3227
3228 if (ANYCX(p)) {
3229 p = structref(p, DOT, op == XREAL ? real : imag);
3230 } else if (op == XIMAG) {
3231 /* XXX sanitycheck? */
3232 tfree(p);
3233 p = bcon(0);
3234 }
3235 return p;
3236}
3237
3238NODE *
3239cxconj(NODE *p)
3240{
3241 NODE *q, *r;
3242
3243 /* XXX side effects? */
3244 q = cxstore(strmemb(p->n_ap)->stype);
3245 r = buildtree(ASSIGN, structref(ccopy(q), DOT, real),
3246 structref(ccopy(p), DOT, real));
3247 r = comop(r, buildtree(ASSIGN, structref(ccopy(q), DOT, imag),
3248 buildtree(UMINUS, structref(p, DOT, imag), NIL)));
3249 return comop(r, q);
3250}
3251
3252/*
3253 * Prepare for return.
3254 * There may be implicit casts to other types.
3255 */
3256NODE *
3257cxret(NODE *p, NODE *q)
3258{
3259//printf("cxret\n");
3260//fwalk(p, eprint, 0);
3261 if (ANYCX(q)) { /* Return complex type */
3262 p = mkcmplx(p, strmemb(q->n_ap)->stype);
3263 } else if (ISFTY(q->n_type) || ISITY(q->n_type)) { /* real or imag */
3264 p = structref(p, DOT, ISFTY(q->n_type) ? real : imag);
3265 if (p->n_type != q->n_type)
3266 p = cast(p, q->n_type, 0);
3267 } else
3268 cerror("cxred failing type");
3269 return p;
3270}
3271#endif
Note: See TracBrowser for help on using the repository browser.