scc

A fork of https://git.simple-cc.org/scc/ for Qute

git clone https://git.8pit.net/scc.git

  1#include <assert.h>
  2#include <inttypes.h>
  3#include <ctype.h>
  4#include <stdio.h>
  5#include <stdlib.h>
  6#include <stdarg.h>
  7
  8#include <scc/scc.h>
  9#include "cc1.h"
 10
 11static void emitbin(int, void *),
 12            emitcast(int, void *),
 13            emitsym(int, void *),
 14            emitexp(int, void *),
 15            emitsymid(int, void *),
 16            emittext(int, void *),
 17            emitfun(int, void *),
 18            emitdcl(int, void *),
 19            emitinit(int, void *),
 20            emittype(int, void *),
 21            emitbuilt(int, void *);
 22
 23char *optxt[] = {
 24	[OADD] = "+",
 25	[OSUB] = "-",
 26	[OMUL] = "*",
 27	[OINC] = ":i",
 28	[ODEC] =  ":d",
 29	[OPTR] = "@",
 30	[OMOD] = "%",
 31	[ODIV] = "/",
 32	[OSHL] = "l",
 33	[OSHR]  = "r",
 34	[OLT] = "<",
 35	[OGT] = ">",
 36	[OGE] = "]",
 37	[OLE] =  "[",
 38	[OEQ] = "=",
 39	[ONE] = "!",
 40	[OBAND] = "&",
 41	[OBXOR]  = "^",
 42	[OBOR] = "|",
 43	[OASSIGN] = ":",
 44	[OA_MUL] = ":*",
 45	[OA_DIV] = ":/",
 46	[OA_MOD] = ":%",
 47	[OA_ADD] = ":+",
 48	[OA_SUB] = ":-",
 49	[OA_SHL] = ":l",
 50	[OA_SHR] = ":r",
 51	[OA_AND] = ":&",
 52	[OA_XOR] = ":^",
 53	[OA_OR] = ":|",
 54	[OADDR] = "'",
 55	[OSNEG] = "_",
 56	[ONEG] = "n",
 57	[OCPL] = "~",
 58	[OAND] = "a",
 59	[OOR] = "o",
 60	[OASK] = "?",
 61	[OCOMMA] = ",",
 62	[OLABEL] = "L%d\n",
 63	[ODEFAULT] = "\tf\tL%d\n",
 64	[OBSWITCH] = "\ts",
 65	[OESWITCH] = "\tt\tL%d\n",
 66	[OCASE] = "\tv\tL%d",
 67	[OJUMP] = "\tj\tL%d\n",
 68	[OBRANCH] = "\ty\tL%d",
 69	[OEFUN] = "}\n",
 70	[OELOOP] = "\te\n",
 71	[OBLOOP] = "\tb\n",
 72	[ORET] = "\th",
 73	[OPAR] = "p",
 74	[OCALL] = "c",
 75	[OCALLE] = "z",
 76	[OFIELD] = "."
 77};
 78
 79void (*opcode[])(int, void *) = {
 80	[OADD] = emitbin,
 81	[OSUB] = emitbin,
 82	[OMUL] = emitbin,
 83	[OINC] = emitbin,
 84	[ODEC] =  emitbin,
 85	[OPTR] = emitbin,
 86	[OMOD] = emitbin,
 87	[ODIV] = emitbin,
 88	[OSHL] = emitbin,
 89	[OSHR]  = emitbin,
 90	[OLT] = emitbin,
 91	[OGT] = emitbin,
 92	[OGE] = emitbin,
 93	[OLE] =  emitbin,
 94	[OEQ] = emitbin,
 95	[ONE] = emitbin,
 96	[OBAND] = emitbin,
 97	[OBXOR]  = emitbin,
 98	[OBOR] = emitbin,
 99	[OASSIGN] = emitbin,
100	[OA_MUL] = emitbin,
101	[OA_DIV] = emitbin,
102	[OA_MOD] = emitbin,
103	[OA_ADD] = emitbin,
104	[OA_SUB] = emitbin,
105	[OA_SHL] = emitbin,
106	[OA_SHR] = emitbin,
107	[OA_AND] = emitbin,
108	[OA_XOR] = emitbin,
109	[OA_OR] = emitbin,
110	[OADDR] = emitbin,
111	[OSNEG] = emitbin,
112	[ONEG] = emitbin,
113	[OCPL] = emitbin,
114	[OAND] = emitbin,
115	[OOR] = emitbin,
116	[OCOMMA] = emitbin,
117	[OCAST] = emitcast,
118	[OSYM] = emitsym,
119	[OASK] = emitbin,
120	[OCOLON] = emitbin,
121	[OFIELD]= emitbin,
122	[OEXPR] = emitexp,
123	[OLABEL] = emitsymid,
124	[ODEFAULT] = emitsymid,
125	[OCASE] = emitsymid,
126	[OJUMP] = emitsymid,
127	[OBRANCH] = emitsymid,
128	[OEFUN] = emittext,
129	[OELOOP] = emittext,
130	[OBLOOP] = emittext,
131	[OFUN] = emitfun,
132	[ORET] = emittext,
133	[ODECL] = emitdcl,
134	[OBSWITCH] = emittext,
135	[OESWITCH] = emitsymid,
136	[OPAR] = emitbin,
137	[OCALL] = emitbin,
138	[OCALLE] = emitbin,
139	[OINIT] = emitinit,
140	[OBUILTIN] = emitbuilt,
141	[OTYP] = emittype,
142};
143
144static FILE *outfp;
145
146void
147icode(void)
148{
149	outfp = stdout;
150}
151
152void
153freetree(Node *np)
154{
155	if (!np)
156		return;
157	freetree(np->left);
158	freetree(np->right);
159	free(np);
160}
161
162static void
163emitnode(Node *np)
164{
165	if (np)
166		(*opcode[np->op])(np->op, np);
167}
168
169Node *
170prtree(char *s, Node *np)
171{
172	FILE *tmp = outfp;
173
174	outfp = stderr;
175	fprintf(outfp, "DBG prtree %s", s);
176	emitnode(np);
177	putc('\n', outfp);
178	outfp = tmp;
179
180	return np;
181}
182
183void
184emit(int op, void *arg)
185{
186	extern int failure;
187
188	if (failure || onlycpp || onlyheader)
189		return;
190	(*opcode[op])(op, arg);
191}
192
193static void
194emitvar(Symbol *sym)
195{
196	int c;
197	short flags = sym->flags;
198
199	if (flags & SLOCAL)
200		c = 'T';
201	else if (flags & SPRIVATE)
202		c =  'Y';
203	else if (flags & SGLOBAL)
204		c = 'G';
205	else if (flags & SREGISTER)
206		c = 'R';
207	else if (flags & SFIELD)
208		c = 'M';
209	else if (flags & SEXTERN)
210		c = 'X';
211	else
212		c = 'A';
213	fprintf(outfp, "%c%u", c, sym->id);
214}
215
216static void
217emitconst(Node *np)
218{
219	int n;
220	unsigned char *fp, *p;
221	Symbol *sym = np->sym;
222	Type *tp = np->type;
223	unsigned long long u;
224
225	switch (tp->op) {
226	case FLOAT:
227		if (tp == floattype)
228			u = *(uint32_t *) &sym->u.f;
229		else if (tp == doubletype)
230			u = *(uint64_t *) &sym->u.d;
231		else
232			abort(); /* TODO: What here?? */
233		goto print;
234	case PTR:
235	case INT:
236	case ENUM:
237		u = (tp->prop & TSIGNED) ? sym->u.i : sym->u.u;
238	print:
239		fprintf(outfp,
240		        "#%c%llX",
241		        tp->letter,
242		        u & ones(tp->size));
243		break;
244	default:
245		abort();
246	}
247}
248
249static void
250emitsym(int op, void *arg)
251{
252	Node *np = arg;
253
254	if ((np->sym->flags & SINITLST) == 0) {
255		/*
256		 * When we have a compound literal we are going
257		 * to call to emitnode for every element of it,
258		 * and it means that we will have two '\t'
259		 * for the first element
260		 */
261		putc('\t', outfp);
262	}
263	(np->flags & NCONST) ? emitconst(np) : emitvar(np->sym);
264}
265
266static void
267emitletter(Type *tp)
268{
269	int letter;
270
271	letter = (tp->prop&TELLIPSIS) ? 'E' : tp->letter;
272	putc(letter, outfp);
273	switch (tp->op) {
274	case ARY:
275	case STRUCT:
276	case UNION:
277		fprintf(outfp, "%u", tp->id);
278	}
279}
280
281static void
282emittype(int op, void *arg)
283{
284	long long n;
285	Symbol **sp;
286	char *tag;
287	Type *tp = arg;
288
289	if (!(tp->prop & TDEFINED))
290		return;
291
292	switch (tp->op) {
293	case ARY:
294		emitletter(tp);
295		putc('\t', outfp);
296		emitletter(tp->type);
297		fprintf(outfp,
298		        "\t#%c%llX\n",
299		        sizettype->letter, (long long) tp->n.elem);
300		return;
301	case UNION:
302	case STRUCT:
303		emitletter(tp);
304		tag = tp->tag->name;
305		fprintf(outfp,
306		       "\t\"%s\t#%c%lX\t#%c%X\n",
307		       (tag) ? tag : "",
308		       sizettype->letter,
309		       tp->size,
310		       sizettype->letter,
311		       tp->align);
312		n = tp->n.elem;
313		for (sp = tp->p.fields; n-- > 0; ++sp)
314			emit(ODECL, *sp);
315		break;
316	case PTR:
317	case FTN:
318	case ENUM:
319		return;
320	default:
321		abort();
322	}
323}
324
325static void
326emitrstring(Symbol *sym, Type *tp)
327{
328	Rune *bp, *lim;
329
330	bp = sym->u.rs;
331	lim = &sym->u.rs[tp->n.elem];
332	while (bp < lim) {
333		fprintf(outfp,
334			"\t#%c%" PRIX32 "\n",
335			wchartype->letter, *bp++);
336	}
337}
338
339static void
340emitstring(Symbol *sym, Type *tp)
341{
342	char *bp, *s, *lim;
343	int n;
344
345	bp = sym->u.s;
346	lim = &sym->u.s[tp->n.elem];
347	while (bp < lim) {
348		s = bp;
349		while (bp < lim && isprint(*bp))
350			++bp;
351		if ((n = bp - s) > 1)
352			fprintf(outfp, "\t#\"%.*s\n", n, s);
353		else
354			bp = s;
355		if (bp == lim)
356			break;
357		do {
358			fprintf(outfp,
359			        "\t#%c%X\n",
360			        chartype->letter, (*bp++) & 0xFF);
361		} while (bp < lim && !isprint(*bp));
362	}
363}
364
365Node *
366zeronode(Type *tp)
367{
368	return simplify(convert(constnode(zero), tp, 0));
369}
370
371static void
372emitpadding(Type *tp, unsigned long long *addr)
373{
374	int i, align;
375	unsigned long long a, n;
376
377	align = tp->align - 1;
378	a = *addr;
379	n = a+align & ~align;
380
381	for ( ; a != n; ++a)
382		emitexp(OEXPR, zeronode(chartype));
383	*addr = n;
384}
385
386static void
387emitdesig(Node *np, Type *tp, unsigned long long *addr)
388{
389	Symbol *sym;
390	unsigned long long n;
391	Node *aux;
392	Type *p;
393
394	emitpadding(tp, addr);
395
396	if (!np) {
397		sym = NULL;
398	} else {
399		if (!np->sym)
400			goto emit_expression;
401		sym = np->sym;
402		if (sym->flags & SSTRING) {
403			emitstring(sym, tp);
404			*addr += tp->n.elem;
405			return;
406		}
407		if (sym->flags & SRSTRING) {
408			emitrstring(sym, tp);
409			*addr += tp->n.elem * wchartype->size;
410			return;
411		}
412		
413		if ((sym->flags & SINITLST) == 0)
414			goto emit_expression;
415	}
416
417	switch (tp->op) {
418	case PTR:
419	case INT:
420	case ENUM:
421		aux = sym ? *sym->u.init : zeronode(tp);
422		*addr += aux->type->size;
423		emitexp(OEXPR, aux);
424		break;
425	case UNION:
426		aux = (sym) ? sym->u.init[0] : NULL;
427		p = (aux) ? aux->type : tp->p.fields[0]->type;
428		emitdesig(aux, p, addr);
429		emitpadding(tp, addr);
430		break;
431	case STRUCT:
432	case ARY:
433		for (n = 0; n < tp->n.elem; ++n) {
434			aux = (sym) ? sym->u.init[n] : NULL;
435			p = (tp->op == ARY) ? tp->type : tp->p.fields[n]->type;
436			emitdesig(aux, p, addr);
437		}
438		emitpadding(tp, addr);
439		break;
440	default:
441		abort();
442	}
443
444	if (sym) {
445		free(sym->u.init);
446		sym->u.init = NULL;
447	}
448	freetree(np);
449	return;
450
451emit_expression:
452	emitexp(OEXPR, np);
453	*addr += tp->size;
454}
455
456static void
457emitinit(int op, void *arg)
458{
459	Node *np = arg;
460	unsigned long long addr = 0;
461
462	fputs("\t(\n", outfp);
463	emitdesig(np, np->type, &addr);
464	fputs(")\n", outfp);
465}
466
467static void
468emitdcl(int op, void *arg)
469{
470	Symbol *sym = arg;
471
472	if (sym->flags & SEMITTED)
473		return;
474	emitvar(sym);
475	putc('\t', outfp);
476	if (sym->type->op == FTN) {
477		emitletter(sym->type->type);
478		putc('\t', outfp);
479	}
480	emitletter(sym->type);
481	fprintf(outfp, "\t\"%s", (sym->name) ? sym->name : "");
482	if (sym->flags & SFIELD)
483		fprintf(outfp, "\t#%c%llX", sizettype->letter, sym->u.i);
484	sym->flags |= SEMITTED;
485	if ((sym->flags & SHASINIT) == 0)
486		putc('\n', outfp);
487}
488
489static void
490emitcast(int op, void *arg)
491{
492	Node *np = arg, *lp = np->left;
493
494	emitnode(lp);
495	if (np->type != voidtype)
496		fprintf(outfp, "\tg%c", np->type->letter);
497}
498
499static void
500emitbin(int op, void *arg)
501{
502	Node *np = arg;
503	char *s;
504
505	emitnode(np->left);
506	emitnode(np->right);
507
508	/* do not print in OCOLON case */
509	if ((s = optxt[op]) != NULL)  {
510		fprintf(outfp, "\t%s", s);
511		emitletter(np->type);
512	}
513}
514
515static void
516emitbuilt(int op, void *arg)
517{
518	Node *np = arg;
519
520	emitnode(np->left);
521	emitnode(np->right);
522	fprintf(outfp, "\t\"%s\tm", np->sym->name);
523	emitletter(np->type);
524}
525
526
527static void
528emitexp(int op, void *arg)
529{
530	Node *np = arg;
531
532	emitnode(np);
533	putc('\n', outfp);
534	freetree(np);
535}
536
537static void
538emitfun(int op, void *arg)
539{
540	Symbol *sym = arg, **sp;
541
542	emitdcl(op, arg);
543	fputs("{\n", outfp);
544
545	for (sp = sym->u.pars; sp && *sp; ++sp)
546		emit(ODECL, *sp);
547	fputs("\\\n", outfp);
548}
549
550static void
551emittext(int op, void *arg)
552{
553	fputs(optxt[op], outfp);
554}
555
556static void
557emitsymid(int op, void *arg)
558{
559	Symbol *sym = arg;
560	fprintf(outfp, optxt[op], sym->id);
561}
562
563Node *
564node(int op, Type *tp, Node *lp, Node *rp)
565{
566	Node *np;
567
568	np = xmalloc(sizeof(*np));
569	np->op = op;
570	np->type = tp;
571	np->sym = NULL;
572	np->flags = 0;
573	np->left = lp;
574	np->right = rp;
575
576	if (lp)
577		np->flags |= lp->flags & NEFFECT;
578	if (rp)
579		np->flags |= rp->flags & NEFFECT;
580	return np;
581}
582
583Node *
584varnode(Symbol *sym)
585{
586	Node *np;
587	Type *tp = sym->type;
588
589	np = node(OSYM, sym->type, NULL, NULL);
590	np->type = sym->type;
591	np->flags = (tp->op != FTN && tp->op != ARY) ? NLVAL : 0;
592	np->sym = sym;
593	return np;
594}
595
596Node *
597constnode(Symbol *sym)
598{
599	Node *np;
600
601	np = node(OSYM, sym->type, NULL, NULL);
602	np->flags = NCONST;
603	np->sym = sym;
604	return np;
605}
606
607Node *
608sizeofnode(Type *tp)
609{
610	Symbol *sym;
611
612	sym = newsym(NS_IDEN, NULL);
613	sym->type = sizettype;
614	sym->flags |= SCONSTANT;
615	sym->u.u = tp->size;
616	DBG("EXPR sizeof %llu", sym->u.u);
617	return constnode(sym);
618}
619
620Node *
621offsetnode(Symbol *field, Type *tp)
622{
623	Symbol *sym;
624
625	assert(field->flags & SFIELD);
626	sym = newsym(NS_IDEN, NULL);
627	sym->type = tp;
628	sym->flags |= SCONSTANT;
629	sym->u.u = field->u.u;
630
631	return constnode(sym);
632}
633
634Node *
635addrnode(unsigned long long u)
636{
637	Symbol *sym;
638
639	sym = newsym(NS_IDEN, NULL);
640	sym->type = pvoidtype;
641	sym->flags |= SCONSTANT;
642	sym->u.u = u;
643
644	return constnode(sym);
645}