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