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