1 #include "c.h"
2 
3 
4 #define add(x,n) (x > inttype->u.sym->u.limits.max.i-(n) ? (overflow=1,x) : x+(n))
5 #define chkoverflow(x,n) ((void)add(x,n))
6 #define bits2bytes(n) (((n) + 7)/8)
7 static int regcount;
8 
9 static List autos, registers;
10 Symbol cfunc;		/* current function */
11 Symbol retv;		/* return value location for structs */
12 
13 static void checkref(Symbol, void *);
14 static Symbol dclglobal(int, char *, Type, Coordinate *);
15 static Symbol dcllocal(int, char *, Type, Coordinate *);
16 static Symbol dclparam(int, char *, Type, Coordinate *);
17 static Type dclr(Type, char **, Symbol **, int);
18 static Type dclr1(char **, Symbol **, int);
19 static void decl(Symbol (*)(int, char *, Type, Coordinate *));
20 extern void doconst(Symbol, void *);
21 static void doglobal(Symbol, void *);
22 static void doextern(Symbol, void *);
23 static void exitparams(Symbol []);
24 static void fields(Type);
25 static void funcdefn(int, char *, Type, Symbol [], Coordinate);
26 static void initglobal(Symbol, int);
27 static void oldparam(Symbol, void *);
28 static Symbol *parameters(Type);
29 static Type specifier(int *);
30 static Type structdcl(int);
31 static Type tnode(int, Type);
program(void)32 void program(void) {
33 	int n;
34 
35 	level = GLOBAL;
36 	for (n = 0; t != EOI; n++)
37 		if (kind[t] == CHAR || kind[t] == STATIC
38 		|| t == ID || t == '*' || t == '(') {
39 			decl(dclglobal);
40 			deallocate(STMT);
41 			if (!(glevel >= 3 || xref))
42 			deallocate(FUNC);
43 		} else if (t == ';') {
44 			warning("empty declaration\n");
45 			t = gettok();
46 		} else {
47 			error("unrecognized declaration\n");
48 			t = gettok();
49 		}
50 	if (n == 0)
51 		warning("empty input file\n");
52 }
specifier(int * sclass)53 static Type specifier(int *sclass) {
54 	int cls, cons, sign, size, type, vol;
55 	Type ty = NULL;
56 
57 	cls = vol = cons = sign = size = type = 0;
58 	if (sclass == NULL)
59 		cls = AUTO;
60 	for (;;) {
61 		int *p, tt = t;
62 		switch (t) {
63 		case AUTO:
64 		case REGISTER: if (level <= GLOBAL && cls == 0)
65 		               	error("invalid use of `%k'\n", t);
66 		               p = &cls;  t = gettok();      break;
67 		case STATIC: case EXTERN:
68 		case TYPEDEF:  p = &cls;  t = gettok();      break;
69 		case CONST:    p = &cons; t = gettok();      break;
70 		case VOLATILE: p = &vol;  t = gettok();      break;
71 		case SIGNED:
72 		case UNSIGNED: p = &sign; t = gettok();      break;
73 		case LONG:     if (size == LONG) {
74 		                       size = 0;
75 		                       tt = LONG+LONG;
76 		               }
77 		               p = &size; t = gettok();      break;
78 		case SHORT:    p = &size; t = gettok();      break;
79 		case VOID: case CHAR: case INT: case FLOAT:
80 		case DOUBLE:   p = &type; ty = tsym->type;
81 		                          t = gettok();      break;
82 		case ENUM:     p = &type; ty = enumdcl();    break;
83 		case STRUCT:
84 		case UNION:    p = &type; ty = structdcl(t); break;
85 		case ID:
86 			if (istypename(t, tsym) && type == 0
87 			&& sign == 0 && size == 0) {
88 				use(tsym, src);
89 				ty = tsym->type;
90 				if (isqual(ty)
91 				&& ty->size != ty->type->size) {
92 					ty = unqual(ty);
93 					if (isconst(tsym->type))
94 						ty = qual(CONST, ty);
95 					if (isvolatile(tsym->type))
96 						ty = qual(VOLATILE, ty);
97 					tsym->type = ty;
98 				}
99 				p = &type;
100 				t = gettok();
101 			} else
102 				p = NULL;
103 			break;
104 		default: p = NULL;
105 		}
106 		if (p == NULL)
107 			break;
108 		if (*p)
109 			error("invalid use of `%k'\n", tt);
110 		*p = tt;
111 	}
112 	if (sclass)
113 		*sclass = cls;
114 	if (type == 0) {
115 		type = INT;
116 		ty = inttype;
117 	}
118 	if ((size == SHORT     && type != INT)
119 	||  (size == LONG+LONG && type != INT)
120 	||  (size == LONG      && type != INT && type != DOUBLE)
121 	||  (sign && type != INT && type != CHAR))
122 		error("invalid type specification\n");
123 	if (type == CHAR && sign)
124 		ty = sign == UNSIGNED ? unsignedchar : signedchar;
125 	else if (size == SHORT)
126 		ty = sign == UNSIGNED ? unsignedshort : shorttype;
127 	else if (size == LONG && type == DOUBLE)
128 		ty = longdouble;
129 	else if (size == LONG+LONG) {
130 		ty = sign == UNSIGNED ? unsignedlonglong : longlong;
131 		if (Aflag >= 1)
132 			warning("`%t' is a non-ANSI type\n", ty);
133 	} else if (size == LONG)
134 		ty = sign == UNSIGNED ? unsignedlong : longtype;
135 	else if (sign == UNSIGNED && type == INT)
136 		ty = unsignedtype;
137 	if (cons == CONST)
138 		ty = qual(CONST, ty);
139 	if (vol  == VOLATILE)
140 		ty = qual(VOLATILE, ty);
141 	return ty;
142 }
decl(Symbol (* dcl)(int,char *,Type,Coordinate *))143 static void decl(Symbol (*dcl)(int, char *, Type, Coordinate *)) {
144 	int sclass;
145 	Type ty, ty1;
146 	static char stop[] = { CHAR, STATIC, ID, 0 };
147 
148 	ty = specifier(&sclass);
149 	if (t == ID || t == '*' || t == '(' || t == '[') {
150 		char *id;
151 		Coordinate pos;
152 		id = NULL;
153 		pos = src;
154 		if (level == GLOBAL) {
155 			Symbol *params = NULL;
156 			ty1 = dclr(ty, &id, &params, 0);
157 			if (params && id && isfunc(ty1)
158 			    && (t == '{' || istypename(t, tsym)
159 			    || (kind[t] == STATIC && t != TYPEDEF))) {
160 				if (sclass == TYPEDEF) {
161 					error("invalid use of `typedef'\n");
162 					sclass = EXTERN;
163 				}
164 				if (ty1->u.f.oldstyle)
165 					exitscope();
166 				funcdefn(sclass, id, ty1, params, pos);
167 				return;
168 			} else if (params)
169 				exitparams(params);
170 		} else
171 			ty1 = dclr(ty, &id, NULL, 0);
172 		for (;;) {
173 			if (Aflag >= 1 && !hasproto(ty1))
174 				warning("missing prototype\n");
175 			if (id == NULL)
176 				error("missing identifier\n");
177 			else if (sclass == TYPEDEF)
178 				{
179 					Symbol p = lookup(id, identifiers);
180 					if (p && p->scope == level)
181 						error("redeclaration of `%s'\n", id);
182 					p = install(id, &identifiers, level,
183 						level < LOCAL ? PERM : FUNC);
184 					p->type = ty1;
185 					p->sclass = TYPEDEF;
186 					p->src = pos;
187 				}
188 			else
189 				(void)(*dcl)(sclass, id, ty1, &pos);
190 			if (t != ',')
191 				break;
192 			t = gettok();
193 			id = NULL;
194 			pos = src;
195 			ty1 = dclr(ty, &id, NULL, 0);
196 		}
197 	} else if (ty == NULL
198 	|| !(isenum(ty) ||
199 	     (isstruct(ty) && (*unqual(ty)->u.sym->name < '1' || *unqual(ty)->u.sym->name > '9'))))
200 		error("empty declaration\n");
201 	test(';', stop);
202 }
dclglobal(int sclass,char * id,Type ty,Coordinate * pos)203 static Symbol dclglobal(int sclass, char *id, Type ty, Coordinate *pos) {
204 	Symbol p;
205 
206 	if (sclass == 0)
207 		sclass = AUTO;
208 	else if (sclass != EXTERN && sclass != STATIC) {
209 		error("invalid storage class `%k' for `%t %s'\n",
210 			sclass, ty, id);
211 		sclass = AUTO;
212 	}
213 	p = lookup(id, identifiers);
214 	if (p && p->scope == GLOBAL) {
215 		if (p->sclass != TYPEDEF && eqtype(ty, p->type, 1))
216 			ty = compose(ty, p->type);
217 		else
218 			error("redeclaration of `%s' previously declared at %w\n", p->name, &p->src);
219 
220 		if (!isfunc(ty) && p->defined && t == '=')
221 			error("redefinition of `%s' previously defined at %w\n", p->name, &p->src);
222 
223 		if ((p->sclass == EXTERN && sclass == STATIC)
224 		||  (p->sclass == STATIC && sclass == AUTO)
225 		||  (p->sclass == AUTO   && sclass == STATIC))
226 			warning("inconsistent linkage for `%s' previously declared at %w\n", p->name, &p->src);
227 
228 	}
229 	if (p == NULL || p->scope != GLOBAL) {
230 		Symbol q = lookup(id, externals);
231 		if (q) {
232 			if (sclass == STATIC || !eqtype(ty, q->type, 1))
233 				warning("declaration of `%s' does not match previous declaration at %w\n", id, &q->src);
234 
235 			p = relocate(id, externals, globals);
236 			p->sclass = sclass;
237 		} else {
238 			p = install(id, &globals, GLOBAL, PERM);
239 			p->sclass = sclass;
240 			(*IR->defsymbol)(p);
241 		}
242 		if (p->sclass != STATIC) {
243 			static int nglobals;
244 			nglobals++;
245 			if (Aflag >= 2 && nglobals == 512)
246 				warning("more than 511 external identifiers\n");
247 		}
248 	} else if (p->sclass == EXTERN)
249 		p->sclass = sclass;
250 	p->type = ty;
251 	p->src = *pos;
252 	if (t == '=' && isfunc(p->type)) {
253 		error("illegal initialization for `%s'\n", p->name);
254 		t = gettok();
255 		initializer(p->type, 0);
256 	} else if (t == '=') {
257 		initglobal(p, 0);
258 		if (glevel > 0 && IR->stabsym) {
259 			(*IR->stabsym)(p); swtoseg(p->u.seg); }
260 	} else if (p->sclass == STATIC && !isfunc(p->type)
261 	&& p->type->size == 0)
262 		error("undefined size for `%t %s'\n", p->type, p->name);
263 	return p;
264 }
initglobal(Symbol p,int flag)265 static void initglobal(Symbol p, int flag) {
266 	Type ty;
267 
268 	if (t == '=' || flag) {
269 		if (p->sclass == STATIC) {
270 			for (ty = p->type; isarray(ty); ty = ty->type)
271 				;
272 			defglobal(p, isconst(ty) ? LIT : DATA);
273 		} else
274 			defglobal(p, DATA);
275 		if (t == '=')
276 			t = gettok();
277 		ty = initializer(p->type, 0);
278 		if (isarray(p->type) && p->type->size == 0)
279 			p->type = ty;
280 		if (p->sclass == EXTERN)
281 			p->sclass = AUTO;
282 	}
283 }
defglobal(Symbol p,int seg)284 void defglobal(Symbol p, int seg) {
285 	p->u.seg = seg;
286 	swtoseg(p->u.seg);
287 	if (p->sclass != STATIC)
288 		(*IR->export)(p);
289 	(*IR->global)(p);
290 	p->defined = 1;
291 }
292 
dclr(Type basety,char ** id,Symbol ** params,int abstract)293 static Type dclr(Type basety, char **id, Symbol **params, int abstract) {
294 	Type ty = dclr1(id, params, abstract);
295 
296 	for ( ; ty; ty = ty->type)
297 		switch (ty->op) {
298 		case POINTER:
299 			basety = ptr(basety);
300 			break;
301 		case FUNCTION:
302 			basety = func(basety, ty->u.f.proto,
303 				ty->u.f.oldstyle);
304 			break;
305 		case ARRAY:
306 			basety = array(basety, ty->size, 0);
307 			break;
308 		case CONST: case VOLATILE:
309 			basety = qual(ty->op, basety);
310 			break;
311 		default: assert(0);
312 		}
313 	if (Aflag >= 2 && basety->size > 32767)
314 		warning("more than 32767 bytes in `%t'\n", basety);
315 	return basety;
316 }
tnode(int op,Type type)317 static Type tnode(int op, Type type) {
318 	Type ty;
319 
320 	NEW0(ty, STMT);
321 	ty->op = op;
322 	ty->type = type;
323 	return ty;
324 }
dclr1(char ** id,Symbol ** params,int abstract)325 static Type dclr1(char **id, Symbol **params, int abstract) {
326 	Type ty = NULL;
327 
328 	switch (t) {
329 	case ID:                if (id)
330 					*id = token;
331 				else
332 					error("extraneous identifier `%s'\n", token);
333 				t = gettok(); break;
334 	case '*': t = gettok(); if (t == CONST || t == VOLATILE) {
335 					Type ty1;
336 					ty1 = ty = tnode(t, NULL);
337 					while ((t = gettok()) == CONST || t == VOLATILE)
338 						ty1 = tnode(t, ty1);
339 					ty->type = dclr1(id, params, abstract);
340 					ty = ty1;
341 				} else
342 					ty = dclr1(id, params, abstract);
343 				ty = tnode(POINTER, ty); break;
344 	case '(': t = gettok(); if (abstract
345 				&& (t == REGISTER || istypename(t, tsym) || t == ')')) {
346 					Symbol *args;
347 					ty = tnode(FUNCTION, ty);
348 					enterscope();
349 					if (level > PARAM)
350 						enterscope();
351 					args = parameters(ty);
352 					exitparams(args);
353 				} else {
354 					ty = dclr1(id, params, abstract);
355 					expect(')');
356 					if (abstract && ty == NULL
357 					&& (id == NULL || *id == NULL))
358 						return tnode(FUNCTION, NULL);
359 				} break;
360 	case '[': break;
361 	default:  return ty;
362 	}
363 	while (t == '(' || t == '[')
364 		switch (t) {
365 		case '(': t = gettok(); { Symbol *args;
366 					  ty = tnode(FUNCTION, ty);
367 					  enterscope();
368 					  if (level > PARAM)
369 					  	enterscope();
370 					  args = parameters(ty);
371 					  if (params && *params == NULL)
372 					  	*params = args;
373 					  else
374 					  	exitparams(args);
375  }
376 		          break;
377 		case '[': t = gettok(); { int n = 0;
378 					  if (kind[t] == ID) {
379 					  	n = intexpr(']', 1);
380 					  	if (n <= 0) {
381 					  		error("`%d' is an illegal array size\n", n);
382 					  		n = 1;
383 					  	}
384 					  } else
385 					  	expect(']');
386 					  ty = tnode(ARRAY, ty);
387 					  ty->size = n; } break;
388 		default: assert(0);
389 		}
390 	return ty;
391 }
parameters(Type fty)392 static Symbol *parameters(Type fty) {
393 	List list = NULL;
394 	Symbol *params;
395 
396 	if (kind[t] == STATIC || istypename(t, tsym)) {
397 		int n = 0;
398 		Type ty1 = NULL;
399 		for (;;) {
400 			Type ty;
401 			int sclass = 0;
402 			char *id = NULL;
403 			if (ty1 && t == ELLIPSIS) {
404 				static struct symbol sentinel;
405 				if (sentinel.type == NULL) {
406 					sentinel.type = voidtype;
407 					sentinel.defined = 1;
408 				}
409 				if (ty1 == voidtype)
410 					error("illegal formal parameter types\n");
411 				list = append(&sentinel, list);
412 				t = gettok();
413 				break;
414 			}
415 			if (!istypename(t, tsym) && t != REGISTER)
416 				error("missing parameter type\n");
417 			n++;
418 			ty = dclr(specifier(&sclass), &id, NULL, 1);
419 			if ( (ty == voidtype && (ty1 || id))
420 			||  ty1 == voidtype)
421 				error("illegal formal parameter types\n");
422 			if (id == NULL)
423 				id = stringd(n);
424 			if (ty != voidtype)
425 				list = append(dclparam(sclass, id, ty, &src), list);
426 			if (Aflag >= 1 && !hasproto(ty))
427 				warning("missing prototype\n");
428 			if (ty1 == NULL)
429 				ty1 = ty;
430 			if (t != ',')
431 				break;
432 			t = gettok();
433 		}
434 		fty->u.f.proto = newarray(length(list) + 1,
435 			sizeof (Type *), PERM);
436 		params = ltov(&list, FUNC);
437 		for (n = 0; params[n]; n++)
438 			fty->u.f.proto[n] = params[n]->type;
439 		fty->u.f.proto[n] = NULL;
440 		fty->u.f.oldstyle = 0;
441 	} else {
442 		if (t == ID)
443 			for (;;) {
444 				Symbol p;
445 				if (t != ID) {
446 					error("expecting an identifier\n");
447 					break;
448 				}
449 				p = dclparam(0, token, inttype, &src);
450 				p->defined = 0;
451 				list = append(p, list);
452 				t = gettok();
453 				if (t != ',')
454 					break;
455 				t = gettok();
456 			}
457 		params = ltov(&list, FUNC);
458 		fty->u.f.proto = NULL;
459 		fty->u.f.oldstyle = 1;
460 	}
461 	if (t != ')') {
462 		static char stop[] = { CHAR, STATIC, IF, ')', 0 };
463 		expect(')');
464 		skipto('{', stop);
465 	}
466 	if (t == ')')
467 		t = gettok();
468 	return params;
469 }
exitparams(Symbol params[])470 static void exitparams(Symbol params[]) {
471 	assert(params);
472 	if (params[0] && !params[0]->defined)
473 		error("extraneous old-style parameter list\n");
474 	if (level > PARAM)
475 		exitscope();
476 	exitscope();
477 }
478 
dclparam(int sclass,char * id,Type ty,Coordinate * pos)479 static Symbol dclparam(int sclass, char *id, Type ty, Coordinate *pos) {
480 	Symbol p;
481 
482 	if (isfunc(ty))
483 		ty = ptr(ty);
484 	else if (isarray(ty))
485 		ty = atop(ty);
486 	if (sclass == 0)
487 		sclass = AUTO;
488 	else if (sclass != REGISTER) {
489 		error("invalid storage class `%k' for `%t%s\n",
490 			sclass, ty, stringf(id ? " %s'" : "' parameter", id));
491 		sclass = AUTO;
492 	} else if (isvolatile(ty) || isstruct(ty)) {
493 		warning("register declaration ignored for `%t%s\n",
494 			ty, stringf(id ? " %s'" : "' parameter", id));
495 		sclass = AUTO;
496 	}
497 
498 	p = lookup(id, identifiers);
499 	if (p && p->scope == level)
500 		error("duplicate declaration for `%s' previously declared at %w\n", id, &p->src);
501 
502 	else
503 		p = install(id, &identifiers, level, FUNC);
504 	p->sclass = sclass;
505 	p->src = *pos;
506 	p->type = ty;
507 	p->defined = 1;
508 	if (t == '=') {
509 		error("illegal initialization for parameter `%s'\n", id);
510 		t = gettok();
511 		(void)expr1(0);
512 	}
513 	return p;
514 }
structdcl(int op)515 static Type structdcl(int op) {
516 	char *tag;
517 	Type ty;
518 	Symbol p;
519 	Coordinate pos;
520 
521 	t = gettok();
522 	pos = src;
523 	if (t == ID) {
524 		tag = token;
525 		t = gettok();
526 	} else
527 		tag = "";
528 	if (t == '{') {
529 		static char stop[] = { IF, ',', 0 };
530 		ty = newstruct(op, tag);
531 		ty->u.sym->src = pos;
532 		ty->u.sym->defined = 1;
533 		t = gettok();
534 		if (istypename(t, tsym))
535 			fields(ty);
536 		else
537 			error("invalid %k field declarations\n", op);
538 		test('}', stop);
539 	}
540 	else if (*tag && (p = lookup(tag, types)) != NULL
541 	&& p->type->op == op) {
542 		ty = p->type;
543 		if (t == ';' && p->scope < level)
544 			ty = newstruct(op, tag);
545 	}
546 	else {
547 		if (*tag == 0)
548 			error("missing %k tag\n", op);
549 		ty = newstruct(op, tag);
550 	}
551 	if (*tag && xref)
552 		use(ty->u.sym, pos);
553 	return ty;
554 }
fields(Type ty)555 static void fields(Type ty) {
556 	{ int n = 0;
557 	  while (istypename(t, tsym)) {
558 	  	static char stop[] = { IF, CHAR, '}', 0 };
559 	  	Type ty1 = specifier(NULL);
560 	  	for (;;) {
561 	  		Field p;
562 	  		char *id = NULL;
563 	  		Type fty = dclr(ty1, &id, NULL, 0);
564 			p = newfield(id, ty, fty);
565 			if (Aflag >= 1 && !hasproto(p->type))
566 				warning("missing prototype\n");
567 			if (t == ':') {
568 				if (unqual(p->type) != inttype
569 				&&  unqual(p->type) != unsignedtype) {
570 					error("`%t' is an illegal bit-field type\n",
571 						p->type);
572 					p->type = inttype;
573 				}
574 				t = gettok();
575 				p->bitsize = intexpr(0, 0);
576 				if (p->bitsize > 8*inttype->size || p->bitsize < 0) {
577 					error("`%d' is an illegal bit-field size\n",
578 						p->bitsize);
579 					p->bitsize = 8*inttype->size;
580 				} else if (p->bitsize == 0 && id) {
581 					warning("extraneous 0-width bit field `%t %s' ignored\n", p->type, id);
582 
583 					p->name = stringd(genlabel(1));
584 				}
585 				p->lsb = 1;
586 			}
587 			else {
588 				if (id == NULL)
589 					error("field name missing\n");
590 				else if (isfunc(p->type))
591 					error("`%t' is an illegal field type\n", p->type);
592 				else if (p->type->size == 0)
593 					error("undefined size for field `%t %s'\n",
594 						p->type, id);
595 			}
596 			if (isconst(p->type))
597 				ty->u.sym->u.s.cfields = 1;
598 			if (isvolatile(p->type))
599 				ty->u.sym->u.s.vfields = 1;
600 	  		n++;
601 	  		if (Aflag >= 2 && n == 128)
602 	  			warning("more than 127 fields in `%t'\n", ty);
603 	  		if (t != ',')
604 	  			break;
605 	  		t = gettok();
606 	  	}
607 	  	test(';', stop);
608 	  } }
609 	{ int bits = 0, off = 0, overflow = 0;
610 	  Field p, *q = &ty->u.sym->u.s.flist;
611 	  ty->align = IR->structmetric.align;
612 	  for (p = *q; p; p = p->link) {
613 	  	int a = p->type->align ? p->type->align : 1;
614 		if (p->lsb)
615 			a = unsignedtype->align;
616 		if (ty->op == UNION)
617 			off = bits = 0;
618 		else if (p->bitsize == 0 || bits == 0
619 		|| bits - 1 + p->bitsize > 8*unsignedtype->size) {
620 			off = add(off, bits2bytes(bits-1));
621 			bits = 0;
622 			chkoverflow(off, a - 1);
623 			off = roundup(off, a);
624 		}
625 		if (a > ty->align)
626 			ty->align = a;
627 		p->offset = off;
628 
629 		if (p->lsb) {
630 			if (bits == 0)
631 				bits = 1;
632 			if (IR->little_endian)
633 				p->lsb = bits;
634 			else
635 				p->lsb = 8*unsignedtype->size - bits + 1
636 					- p->bitsize + 1;
637 			bits += p->bitsize;
638 		} else
639 			off = add(off, p->type->size);
640 		if (off + bits2bytes(bits-1) > ty->size)
641 			ty->size = off + bits2bytes(bits-1);
642 	  	if (p->name == NULL
643 	  	|| !('1' <= *p->name && *p->name <= '9')) {
644 	  		*q = p;
645 	  		q = &p->link;
646 	  	}
647 	  }
648 	  *q = NULL;
649 	  chkoverflow(ty->size, ty->align - 1);
650 	  ty->size = roundup(ty->size, ty->align);
651 	  if (overflow) {
652 	  	error("size of `%t' exceeds %d bytes\n", ty, inttype->u.sym->u.limits.max.i);
653 	  	ty->size = inttype->u.sym->u.limits.max.i&(~(ty->align - 1));
654 	  } }
655 }
funcdefn(int sclass,char * id,Type ty,Symbol params[],Coordinate pt)656 static void funcdefn(int sclass, char *id, Type ty, Symbol params[], Coordinate pt) {
657 	int i, n;
658 	Symbol *callee, *caller, p;
659 	Type rty = freturn(ty);
660 
661 	if (isstruct(rty) && rty->size == 0)
662 		error("illegal use of incomplete type `%t'\n", rty);
663 	for (n = 0; params[n]; n++)
664 		;
665 	if (n > 0 && params[n-1]->name == NULL)
666 		params[--n] = NULL;
667 	if (Aflag >= 2 && n > 31)
668 		warning("more than 31 parameters in function `%s'\n", id);
669 	if (ty->u.f.oldstyle) {
670 		if (Aflag >= 1)
671 			warning("old-style function definition for `%s'\n", id);
672 		caller = params;
673 		callee = newarray(n + 1, sizeof *callee, FUNC);
674 		memcpy(callee, caller, (n+1)*sizeof *callee);
675 		enterscope();
676 		assert(level == PARAM);
677 		while (kind[t] == STATIC || istypename(t, tsym))
678 			decl(dclparam);
679 		foreach(identifiers, PARAM, oldparam, callee);
680 
681 		for (i = 0; (p = callee[i]) != NULL; i++) {
682 			if (!p->defined)
683 				callee[i] = dclparam(0, p->name, inttype, &p->src);
684 			*caller[i] = *p;
685 			caller[i]->sclass = AUTO;
686 			caller[i]->type = promote(p->type);
687 		}
688 		p = lookup(id, identifiers);
689 		if (p && p->scope == GLOBAL && isfunc(p->type)
690 		&& p->type->u.f.proto) {
691 			Type *proto = p->type->u.f.proto;
692 			for (i = 0; caller[i] && proto[i]; i++) {
693 				Type ty = unqual(proto[i]);
694 				if (eqtype(isenum(ty) ? ty->type : ty,
695 					unqual(caller[i]->type), 1) == 0)
696 					break;
697 				else if (isenum(ty) && !isenum(unqual(caller[i]->type)))
698 					warning("compatibility of `%t' and `%t' is compiler dependent\n",
699 						proto[i], caller[i]->type);
700 			}
701 			if (proto[i] || caller[i])
702 				error("conflicting argument declarations for function `%s'\n", id);
703 
704 		}
705 		else {
706 			Type *proto = newarray(n + 1, sizeof *proto, PERM);
707 			if (Aflag >= 1)
708 				warning("missing prototype for `%s'\n", id);
709 			for (i = 0; i < n; i++)
710 				proto[i] = caller[i]->type;
711 			proto[i] = NULL;
712 			ty = func(rty, proto, 1);
713 		}
714 	} else {
715 		callee = params;
716 		caller = newarray(n + 1, sizeof *caller, FUNC);
717 		for (i = 0; (p = callee[i]) != NULL && p->name; i++) {
718 			NEW(caller[i], FUNC);
719 			*caller[i] = *p;
720 			if (isint(p->type))
721 				caller[i]->type = promote(p->type);
722 			caller[i]->sclass = AUTO;
723 			if ('1' <= *p->name && *p->name <= '9')
724 				error("missing name for parameter %d to function `%s'\n", i + 1, id);
725 
726 		}
727 		caller[i] = NULL;
728 	}
729 	for (i = 0; (p = callee[i]) != NULL; i++)
730 		if (p->type->size == 0) {
731 			error("undefined size for parameter `%t %s'\n",
732 				p->type, p->name);
733 			caller[i]->type = p->type = inttype;
734 		}
735 	if (Aflag >= 2 && sclass != STATIC && strcmp(id, "main") == 0) {
736 		if (ty->u.f.oldstyle)
737 			warning("`%t %s()' is a non-ANSI definition\n", rty, id);
738 		else if (!(rty == inttype
739 			&& ((n == 0 && callee[0] == NULL)
740 			||  (n == 2 && callee[0]->type == inttype
741 			&& isptr(callee[1]->type) && callee[1]->type->type == charptype
742 			&& !variadic(ty)))))
743 			warning("`%s' is a non-ANSI definition\n", typestring(ty, id));
744 	}
745 	p = lookup(id, identifiers);
746 	if (p && isfunc(p->type) && p->defined)
747 		error("redefinition of `%s' previously defined at %w\n",
748 			p->name, &p->src);
749 	cfunc = dclglobal(sclass, id, ty, &pt);
750 	cfunc->u.f.label = genlabel(1);
751 	cfunc->u.f.callee = callee;
752 	cfunc->u.f.pt = src;
753 	cfunc->defined = 1;
754 	if (xref)
755 		use(cfunc, cfunc->src);
756 	if (Pflag)
757 		printproto(cfunc, cfunc->u.f.callee);
758 	if (ncalled >= 0)
759 		ncalled = findfunc(cfunc->name, pt.file);
760 	labels   = table(NULL, LABELS);
761 	stmtlabs = table(NULL, LABELS);
762 	refinc = 1.0;
763 	regcount = 0;
764 	codelist = &codehead;
765 	codelist->next = NULL;
766 	if (!IR->wants_callb && isstruct(rty))
767 		retv = genident(AUTO, ptr(rty), PARAM);
768 	compound(0, NULL, 0);
769 
770 	{
771 		Code cp;
772 		for (cp = codelist; cp->kind < Label; cp = cp->prev)
773 			;
774 		if (cp->kind != Jump) {
775 			if (rty != voidtype) {
776 				warning("missing return value\n");
777 				retcode(cnsttree(inttype, 0L));
778 			} else
779 				retcode(NULL);
780 		}
781 	}
782 	definelab(cfunc->u.f.label);
783 	if (events.exit)
784 		apply(events.exit, cfunc, NULL);
785 	walk(NULL, 0, 0);
786 	exitscope();
787 	assert(level == PARAM);
788 	foreach(identifiers, level, checkref, NULL);
789 	if (!IR->wants_callb && isstruct(rty)) {
790 		Symbol *a;
791 		a = newarray(n + 2, sizeof *a, FUNC);
792 		a[0] = retv;
793 		memcpy(&a[1], callee, (n+1)*sizeof *callee);
794 		callee = a;
795 		a = newarray(n + 2, sizeof *a, FUNC);
796 		NEW(a[0], FUNC);
797 		*a[0] = *retv;
798 		memcpy(&a[1], caller, (n+1)*sizeof *callee);
799 		caller = a;
800 	}
801 	if (!IR->wants_argb)
802 		for (i = 0; caller[i]; i++)
803 			if (isstruct(caller[i]->type)) {
804 				caller[i]->type = ptr(caller[i]->type);
805 				callee[i]->type = ptr(callee[i]->type);
806 				caller[i]->structarg = callee[i]->structarg = 1;
807 			}
808 	if (glevel > 1)	for (i = 0; callee[i]; i++) callee[i]->sclass = AUTO;
809 	if (cfunc->sclass != STATIC)
810 		(*IR->export)(cfunc);
811 	if (glevel && IR->stabsym) {
812 		swtoseg(CODE); (*IR->stabsym)(cfunc); }
813 	swtoseg(CODE);
814 	(*IR->function)(cfunc, caller, callee, cfunc->u.f.ncalls);
815 	if (glevel && IR->stabfend)
816 		(*IR->stabfend)(cfunc, lineno);
817 	foreach(stmtlabs, LABELS, checklab, NULL);
818 	exitscope();
819 	expect('}');
820 	labels = stmtlabs = NULL;
821 	retv  = NULL;
822 	cfunc = NULL;
823 }
oldparam(Symbol p,void * cl)824 static void oldparam(Symbol p, void *cl) {
825 	int i;
826 	Symbol *callee = cl;
827 
828 	for (i = 0; callee[i]; i++)
829 		if (p->name == callee[i]->name) {
830 			callee[i] = p;
831 			return;
832 		}
833 	error("declared parameter `%s' is missing\n", p->name);
834 }
compound(int loop,struct swtch * swp,int lev)835 void compound(int loop, struct swtch *swp, int lev) {
836 	Code cp;
837 	int nregs;
838 
839 	walk(NULL, 0, 0);
840 	cp = code(Blockbeg);
841 	enterscope();
842 	assert(level >= LOCAL);
843 	if (level == LOCAL && events.entry)
844 		apply(events.entry, cfunc, NULL);
845 	definept(NULL);
846 	expect('{');
847 	autos = registers = NULL;
848 	if (level == LOCAL && IR->wants_callb
849 	&& isstruct(freturn(cfunc->type))) {
850 		retv = genident(AUTO, ptr(freturn(cfunc->type)), level);
851 		retv->defined = 1;
852 		retv->ref = 1;
853 		registers = append(retv, registers);
854 	}
855 	while (kind[t] == CHAR || kind[t] == STATIC
856 	|| (istypename(t, tsym) && getchr() != ':'))
857 		decl(dcllocal);
858 	{
859 		int i;
860 		Symbol *a = ltov(&autos, STMT);
861 		nregs = length(registers);
862 		for (i = 0; a[i]; i++)
863 			registers = append(a[i], registers);
864 		cp->u.block.locals = ltov(&registers, FUNC);
865 	}
866 	if (events.blockentry)
867 		apply(events.blockentry, cp->u.block.locals, NULL);
868 	while (kind[t] == IF || kind[t] == ID)
869 		statement(loop, swp, lev);
870 	walk(NULL, 0, 0);
871 	foreach(identifiers, level, checkref, NULL);
872 	{
873 		int i = nregs, j;
874 		Symbol p;
875 		for ( ; (p = cp->u.block.locals[i]) != NULL; i++) {
876 			for (j = i; j > nregs
877 				&& cp->u.block.locals[j-1]->ref < p->ref; j--)
878 				cp->u.block.locals[j] = cp->u.block.locals[j-1];
879 			cp->u.block.locals[j] = p;
880 		}
881 	}
882 	if (events.blockexit)
883 		apply(events.blockexit, cp->u.block.locals, NULL);
884 	cp->u.block.level = level;
885 	cp->u.block.identifiers = identifiers;
886 	cp->u.block.types = types;
887 	code(Blockend)->u.begin = cp;
888 	if (reachable(Gen))
889 		definept(NULL);
890 	if (level > LOCAL) {
891 		exitscope();
892 		expect('}');
893 	}
894 }
checkref(Symbol p,void * cl)895 static void checkref(Symbol p, void *cl) {
896 	if (p->scope >= PARAM
897 	&& (isvolatile(p->type) || isfunc(p->type)))
898 		p->addressed = 1;
899 	if (Aflag >= 2 && p->defined && p->ref == 0) {
900 		if (p->sclass == STATIC)
901 			warning("static `%t %s' is not referenced\n",
902 				p->type, p->name);
903 		else if (p->scope == PARAM)
904 			warning("parameter `%t %s' is not referenced\n",
905 				p->type, p->name);
906 		else if (p->scope >= LOCAL && p->sclass != EXTERN)
907 			warning("local `%t %s' is not referenced\n",
908 				p->type, p->name);
909 	}
910 	if (p->sclass == AUTO
911 	&& ((p->scope  == PARAM && regcount == 0)
912 	 || p->scope  >= LOCAL)
913 	&& !p->addressed && isscalar(p->type) && p->ref >= 3.0)
914 		p->sclass = REGISTER;
915 	if (level == GLOBAL && p->sclass == STATIC && !p->defined
916 	&& isfunc(p->type) && p->ref)
917 		error("undefined static `%t %s'\n", p->type, p->name);
918 	assert(!(level == GLOBAL && p->sclass == STATIC && !p->defined && !isfunc(p->type)));
919 }
dcllocal(int sclass,char * id,Type ty,Coordinate * pos)920 static Symbol dcllocal(int sclass, char *id, Type ty, Coordinate *pos) {
921 	Symbol p, q;
922 
923 	if (sclass == 0)
924 		sclass = isfunc(ty) ? EXTERN : AUTO;
925 	else if (isfunc(ty) && sclass != EXTERN) {
926 		error("invalid storage class `%k' for `%t %s'\n",
927 			sclass, ty, id);
928 		sclass = EXTERN;
929 	} else if (sclass == REGISTER
930 	&& (isvolatile(ty) || isstruct(ty) || isarray(ty))) {
931 		warning("register declaration ignored for `%t %s'\n",
932 			ty, id);
933 		sclass = AUTO;
934 	}
935 	q = lookup(id, identifiers);
936 	if ((q && q->scope >= level)
937 	||  (q && q->scope == PARAM && level == LOCAL)) {
938 		if (sclass == EXTERN && q->sclass == EXTERN
939 		&& eqtype(q->type, ty, 1))
940 			ty = compose(ty, q->type);
941 		else
942 			error("redeclaration of `%s' previously declared at %w\n", q->name, &q->src);
943 	}
944 
945 	assert(level >= LOCAL);
946 	p = install(id, &identifiers, level, sclass == STATIC || sclass == EXTERN ? PERM : FUNC);
947 	p->type = ty;
948 	p->sclass = sclass;
949 	p->src = *pos;
950 	switch (sclass) {
951 	case EXTERN:   q = lookup(id, globals);
952 		       if (q == NULL || q->sclass == TYPEDEF || q->sclass == ENUM) {
953 		       	q = lookup(id, externals);
954 		       	if (q == NULL) {
955 		       		q = install(p->name, &externals, GLOBAL, PERM);
956 		       		q->type = p->type;
957 		       		q->sclass = EXTERN;
958 		       		q->src = src;
959 		       		(*IR->defsymbol)(q);
960 		       	}
961 		       }
962 		       if (!eqtype(p->type, q->type, 1))
963 		       	warning("declaration of `%s' does not match previous declaration at %w\n", q->name, &q->src);
964 
965 		       p->u.alias = q; break;
966 	case STATIC:   (*IR->defsymbol)(p);
967 		       initglobal(p, 0);
968 		       if (!p->defined) {
969 		       	if (p->type->size > 0) {
970 		       		defglobal(p, BSS);
971 		       		(*IR->space)(p->type->size);
972 		       	} else
973 		       		error("undefined size for `%t %s'\n",
974 		       			p->type, p->name);
975 		       }
976 		       p->defined = 1; break;
977 	case REGISTER: registers = append(p, registers);
978 		       regcount++;
979 		       p->defined = 1;
980  break;
981 	case AUTO:     autos = append(p, autos);
982 		       p->defined = 1; break;
983 	default: assert(0);
984 	}
985 	if (t == '=') {
986 		Tree e;
987 		if (sclass == EXTERN)
988 			error("illegal initialization of `extern %s'\n", id);
989 		t = gettok();
990 		definept(NULL);
991 		if (isscalar(p->type)
992 		||  (isstruct(p->type) && t != '{')) {
993 			if (t == '{') {
994 				t = gettok();
995 				e = expr1(0);
996 				expect('}');
997 			} else
998 				e = expr1(0);
999 		} else {
1000 			Symbol t1;
1001 			Type ty = p->type, ty1 = ty;
1002 			while (isarray(ty1))
1003 				ty1 = ty1->type;
1004 			if (!isconst(ty) && (!isarray(ty) || !isconst(ty1)))
1005 				ty = qual(CONST, ty);
1006 			t1 = genident(STATIC, ty, GLOBAL);
1007 			initglobal(t1, 1);
1008 			if (isarray(p->type) && p->type->size == 0
1009 			&& t1->type->size > 0)
1010 				p->type = array(p->type->type,
1011 					t1->type->size/t1->type->type->size, 0);
1012 			e = idtree(t1);
1013 		}
1014 		walk(root(asgn(p, e)), 0, 0);
1015 		p->ref = 1;
1016 	}
1017 	if (!isfunc(p->type) && p->defined && p->type->size <= 0)
1018 		error("undefined size for `%t %s'\n", p->type, id);
1019 	return p;
1020 }
finalize(void)1021 void finalize(void) {
1022 	foreach(externals,   GLOBAL,    doextern, NULL);
1023 	foreach(identifiers, GLOBAL,    doglobal, NULL);
1024 	foreach(identifiers, GLOBAL,    checkref, NULL);
1025 	foreach(constants,   CONSTANTS, doconst,  NULL);
1026 }
doextern(Symbol p,void * cl)1027 static void doextern(Symbol p, void *cl) {
1028 	(*IR->import)(p);
1029 }
doglobal(Symbol p,void * cl)1030 static void doglobal(Symbol p, void *cl) {
1031 	if (!p->defined && (p->sclass == EXTERN
1032 	|| (isfunc(p->type) && p->sclass == AUTO)))
1033 		(*IR->import)(p);
1034 	else if (!p->defined && !isfunc(p->type)
1035 	&& (p->sclass == AUTO || p->sclass == STATIC)) {
1036 		if (isarray(p->type)
1037 		&& p->type->size == 0 && p->type->type->size > 0)
1038 			p->type = array(p->type->type, 1, 0);
1039 		if (p->type->size > 0) {
1040 			defglobal(p, BSS);
1041 			(*IR->space)(p->type->size);
1042 			if (glevel > 0 && IR->stabsym)
1043 				(*IR->stabsym)(p);
1044 		} else
1045 			error("undefined size for `%t %s'\n",
1046 				p->type, p->name);
1047 		p->defined = 1;
1048 	}
1049 	if (Pflag
1050 	&& !isfunc(p->type)
1051 	&& !p->generated && p->sclass != EXTERN)
1052 		printdecl(p, p->type);
1053 }
doconst(Symbol p,void * cl)1054 void doconst(Symbol p, void *cl) {
1055 	if (p->u.c.loc) {
1056 		assert(p->u.c.loc->u.seg == 0);
1057 		defglobal(p->u.c.loc, LIT);
1058 		if (isarray(p->type) && p->type->type == widechar) {
1059 			unsigned int *s = p->u.c.v.p;
1060 			int n = p->type->size/widechar->size;
1061 			while (n-- > 0) {
1062 				Value v;
1063 				v.u = *s++;
1064 				(*IR->defconst)(widechar->op, widechar->size, v);
1065 			}
1066 		} else if (isarray(p->type))
1067 			(*IR->defstring)(p->type->size, p->u.c.v.p);
1068 		else
1069 			(*IR->defconst)(p->type->op, p->type->size, p->u.c.v);
1070 		p->u.c.loc = NULL;
1071 	}
1072 }
checklab(Symbol p,void * cl)1073 void checklab(Symbol p, void *cl) {
1074 	if (!p->defined)
1075 		error("undefined label `%s'\n", p->name);
1076 	p->defined = 1;
1077 }
1078 
enumdcl(void)1079 Type enumdcl(void) {
1080 	char *tag;
1081 	Type ty;
1082 	Symbol p = {0};
1083 	Coordinate pos;
1084 
1085 	t = gettok();
1086 	pos = src;
1087 	if (t == ID) {
1088 		tag = token;
1089 		t = gettok();
1090 	} else
1091 		tag = "";
1092 	if (t == '{') {
1093 		static char follow[] = { IF, 0 };
1094 		int n = 0;
1095 		long k = -1;
1096 		List idlist = 0;
1097 		ty = newstruct(ENUM, tag);
1098 		t = gettok();
1099 		if (t != ID)
1100 			error("expecting an enumerator identifier\n");
1101 		while (t == ID) {
1102 			char *id = token;
1103 			Coordinate s;
1104 			if (tsym && tsym->scope == level)
1105 				error("redeclaration of `%s' previously declared at %w\n",
1106 					token, &tsym->src);
1107 			s = src;
1108 			t = gettok();
1109 			if (t == '=') {
1110 				t = gettok();
1111 				k = intexpr(0, 0);
1112 			} else {
1113 				if (k == inttype->u.sym->u.limits.max.i)
1114 					error("overflow in value for enumeration constant `%s'\n", id);
1115 				k++;
1116 			}
1117 			p = install(id, &identifiers, level,  level < LOCAL ? PERM : FUNC);
1118 			p->src = s;
1119 			p->type = ty;
1120 			p->sclass = ENUM;
1121 			p->u.value = k;
1122 			idlist = append(p, idlist);
1123 			n++;
1124 			if (Aflag >= 2 && n == 128)
1125 				warning("more than 127 enumeration constants in `%t'\n", ty);
1126 			if (t != ',')
1127 				break;
1128 			t = gettok();
1129 			if (Aflag >= 2 && t == '}')
1130 				warning("non-ANSI trailing comma in enumerator list\n");
1131 		}
1132 		test('}', follow);
1133 		ty->type = inttype;
1134 		ty->size = ty->type->size;
1135 		ty->align = ty->type->align;
1136 		ty->u.sym->u.idlist = ltov(&idlist, PERM);
1137 		ty->u.sym->defined = 1;
1138 	} else if ((p = lookup(tag, types)) != NULL && p->type->op == ENUM) {
1139 		ty = p->type;
1140 		if (t == ';')
1141 			error("empty declaration\n");
1142 	} else {
1143 		error("unknown enumeration `%s'\n",  tag);
1144 		ty = newstruct(ENUM, tag);
1145 		ty->type = inttype;
1146 	}
1147 	if (*tag && xref)
1148 		use(p, pos);
1149 	return ty;
1150 }
1151 
typename(void)1152 Type typename(void) {
1153 	Type ty = specifier(NULL);
1154 
1155 	if (t == '*' || t == '(' || t == '[') {
1156 		ty = dclr(ty, NULL, NULL, 1);
1157 		if (Aflag >= 1 && !hasproto(ty))
1158 			warning("missing prototype\n");
1159 	}
1160 	return ty;
1161 }
1162 
1163