scc

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

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

  1#include <stdio.h>
  2#include <stdlib.h>
  3#include <string.h>
  4
  5#include <scc/cstd.h>
  6#include <scc/scc.h>
  7
  8#include "../cc2.h"
  9#include "arch.h"
 10
 11#define ADDR_LEN (INTIDENTSIZ+64)
 12
 13static void binary(void), unary(void), store(void), jmp(void), ret(void),
 14            branch(void), call(void), ecall(void), param(void),
 15            asalloc(void), form2local(void), blit(void), vastart(void),
 16            vaarg(void);
 17
 18static struct opdata {
 19	void (*fun)(void);
 20	char *txt;
 21	char letter;
 22} optbl [] = {
 23	[ASLDSB]  =  {.fun = unary,  .txt = "loadsb", .letter = 'w'},
 24	[ASLDUB]  =  {.fun = unary,  .txt = "loadub", .letter = 'w'},
 25	[ASLDSH]  =  {.fun = unary,  .txt = "loadsh", .letter = 'w'},
 26	[ASLDUH]  =  {.fun = unary,  .txt = "loaduh", .letter = 'w'},
 27	[ASLDSW]  =  {.fun = unary,  .txt = "loadsw", .letter = 'w'},
 28	[ASLDUW]  =  {.fun = unary,  .txt = "loaduw", .letter = 'w'},
 29	[ASLDL]   =  {.fun = unary,  .txt = "loadl", .letter = 'l'},
 30	[ASLDS]   =  {.fun = unary,  .txt = "loads", .letter = 's'},
 31	[ASLDD]   =  {.fun = unary,  .txt = "loadd", .letter = 'd'},
 32
 33	[ASCOPYB] =  {.fun = unary,  .txt = "copy", .letter = 'b'},
 34	[ASCOPYH] =  {.fun = unary,  .txt = "copy", .letter = 'h'},
 35	[ASCOPYW] =  {.fun = unary,  .txt = "copy", .letter = 'w'},
 36	[ASCOPYL] =  {.fun = unary,  .txt = "copy", .letter = 'l'},
 37	[ASCOPYS] =  {.fun = unary,  .txt = "copy", .letter = 's'},
 38	[ASCOPYD] =  {.fun = unary,  .txt = "copy", .letter = 'd'},
 39
 40	[ASSTB]   =  {.fun = store,  .txt = "store", .letter = 'b'},
 41	[ASSTH]   =  {.fun = store,  .txt = "store", .letter = 'h'},
 42	[ASSTW]   =  {.fun = store,  .txt = "store", .letter = 'w'},
 43	[ASSTL]   =  {.fun = store,  .txt = "store", .letter = 'l'},
 44	[ASSTM]   =  {.fun = blit},
 45	[ASSTS]   =  {.fun = store,  .txt = "store", .letter = 's'},
 46	[ASSTD]   =  {.fun = store,  .txt = "store", .letter = 'd'},
 47
 48	[ASADDW]  =  {.fun = binary, .txt = "add", .letter = 'w'},
 49	[ASSUBW]  =  {.fun = binary, .txt = "sub", .letter = 'w'},
 50	[ASMULW]  =  {.fun = binary, .txt = "mul", .letter = 'w'},
 51	[ASMODW]  =  {.fun = binary, .txt = "rem", .letter = 'w'},
 52	[ASUMODW] =  {.fun = binary, .txt = "urem", .letter = 'w'},
 53	[ASDIVW]  =  {.fun = binary, .txt = "div", .letter = 'w'},
 54	[ASUDIVW] =  {.fun = binary, .txt = "udiv", .letter = 'w'},
 55	[ASSHLW]  =  {.fun = binary, .txt = "shl", .letter = 'w'},
 56	[ASSHRW]  =  {.fun = binary, .txt = "sar", .letter = 'w'},
 57	[ASUSHRW] =  {.fun = binary, .txt = "shr", .letter = 'w'},
 58	[ASLTW]   =  {.fun = binary, .txt = "csltw", .letter = 'w'},
 59	[ASULTW]  =  {.fun = binary, .txt = "cultw", .letter = 'w'},
 60	[ASGTW]   =  {.fun = binary, .txt = "csgtw", .letter = 'w'},
 61	[ASUGTW]  =  {.fun = binary, .txt = "cugtw", .letter = 'w'},
 62	[ASLEW]   =  {.fun = binary, .txt = "cslew", .letter = 'w'},
 63	[ASULEW]  =  {.fun = binary, .txt = "culew", .letter = 'w'},
 64	[ASGEW]   =  {.fun = binary, .txt = "csgew", .letter = 'w'},
 65	[ASUGEW]  =  {.fun = binary, .txt = "cugew", .letter = 'w'},
 66	[ASEQW]   =  {.fun = binary, .txt = "ceqw", .letter = 'w'},
 67	[ASNEW]   =  {.fun = binary, .txt = "cnew", .letter = 'w'},
 68	[ASBANDW] =  {.fun = binary, .txt = "and", .letter = 'w'},
 69	[ASBORW]  =  {.fun = binary, .txt = "or", .letter = 'w'},
 70	[ASBXORW] =  {.fun = binary, .txt = "xor", .letter = 'w'},
 71
 72	[ASADDL]  =  {.fun = binary, .txt = "add", .letter = 'l'},
 73	[ASSUBL]  =  {.fun = binary, .txt = "sub", .letter = 'l'},
 74	[ASMULL]  =  {.fun = binary, .txt = "mul", .letter = 'l'},
 75	[ASMODL]  =  {.fun = binary, .txt = "rem", .letter = 'l'},
 76	[ASUMODL] =  {.fun = binary, .txt = "urem", .letter = 'l'},
 77	[ASDIVL]  =  {.fun = binary, .txt = "div", .letter = 'l'},
 78	[ASUDIVL] =  {.fun = binary, .txt = "udiv", .letter = 'l'},
 79	[ASSHLL]  =  {.fun = binary, .txt = "shl", .letter = 'l'},
 80	[ASSHRL]  =  {.fun = binary, .txt = "sar", .letter = 'l'},
 81	[ASUSHRL] =  {.fun = binary, .txt = "shr", .letter = 'l'},
 82	[ASLTL]   =  {.fun = binary, .txt = "csltl", .letter = 'w'},
 83	[ASULTL]  =  {.fun = binary, .txt = "cultl", .letter = 'w'},
 84	[ASGTL]   =  {.fun = binary, .txt = "csgtl", .letter = 'w'},
 85	[ASUGTL]  =  {.fun = binary, .txt = "cugtl", .letter = 'w'},
 86	[ASLEL]   =  {.fun = binary, .txt = "cslel", .letter = 'w'},
 87	[ASULEL]  =  {.fun = binary, .txt = "culel", .letter = 'w'},
 88	[ASGEL]   =  {.fun = binary, .txt = "csgel", .letter = 'w'},
 89	[ASUGEL]  =  {.fun = binary, .txt = "cugel", .letter = 'w'},
 90	[ASEQL]   =  {.fun = binary, .txt = "ceql", .letter = 'w'},
 91	[ASNEL]   =  {.fun = binary, .txt = "cnel", .letter = 'w'},
 92	[ASBANDL] =  {.fun = binary, .txt = "and", .letter = 'l'},
 93	[ASBORL]  =  {.fun = binary, .txt = "or", .letter = 'l'},
 94	[ASBXORL] =  {.fun = binary, .txt = "xor", .letter = 'l'},
 95
 96	[ASADDS]  =  {.fun = binary, .txt = "add", .letter = 's'},
 97	[ASSUBS]  =  {.fun = binary, .txt = "sub", .letter = 's'},
 98	[ASMULS]  =  {.fun = binary, .txt = "mul", .letter = 's'},
 99	[ASDIVS]  =  {.fun = binary, .txt = "div", .letter = 's'},
100	[ASLTS]   =  {.fun = binary, .txt = "clts", .letter = 'w'},
101	[ASGTS]   =  {.fun = binary, .txt = "cgts", .letter = 'w'},
102	[ASLES]   =  {.fun = binary, .txt = "cles", .letter = 'w'},
103	[ASGES]   =  {.fun = binary, .txt = "cges", .letter = 'w'},
104	[ASEQS]   =  {.fun = binary, .txt = "ceqs", .letter = 'w'},
105	[ASNES]   =  {.fun = binary, .txt = "cnes", .letter = 'w'},
106
107	[ASADDD]  =  {.fun = binary, .txt = "add", .letter = 'd'},
108	[ASSUBD]  =  {.fun = binary, .txt = "sub", .letter = 'd'},
109	[ASMULD]  =  {.fun = binary, .txt = "mul", .letter = 'd'},
110	[ASDIVD]  =  {.fun = binary, .txt = "div", .letter = 'd'},
111	[ASLTD]   =  {.fun = binary, .txt = "cltd", .letter = 'w'},
112	[ASGTD]   =  {.fun = binary, .txt = "cgtd", .letter = 'w'},
113	[ASLED]   =  {.fun = binary, .txt = "cled", .letter = 'w'},
114	[ASGED]   =  {.fun = binary, .txt = "cged", .letter = 'w'},
115	[ASEQD]   =  {.fun = binary, .txt = "ceqd", .letter = 'w'},
116	[ASNED]   =  {.fun = binary, .txt = "cned", .letter = 'w'},
117
118	[ASEXTBW] =  {.fun = unary, .txt = "extsb", .letter = 'w'},
119	[ASUEXTBW]=  {.fun = unary, .txt = "extub", .letter = 'w'},
120	[ASEXTBL] =  {.fun = unary, .txt = "extsb", .letter = 'l'},
121	[ASUEXTBL]=  {.fun = unary, .txt = "extub", .letter = 'l'},
122	[ASEXTHW] =  {.fun = unary, .txt = "extsh", .letter = 'w'},
123	[ASUEXTHW]=  {.fun = unary, .txt = "extuh", .letter = 'w'},
124	[ASEXTHL] =  {.fun = unary, .txt = "extsh", .letter = 'l'},
125	[ASUEXTHL]=  {.fun = unary, .txt = "extuh", .letter = 'l'},
126	[ASEXTWL] =  {.fun = unary, .txt = "extsw", .letter = 'l'},
127	[ASUEXTWL]=  {.fun = unary, .txt = "extuw", .letter = 'l'},
128
129	[ASSTOL] = {.fun = unary, .txt = "stosi", .letter = 'l'},
130	[ASSTOUL] = {.fun = unary, .txt = "stoui", .letter = 'l'},
131	[ASSTOW] = {.fun = unary, .txt = "stosi", .letter = 'w'},
132	[ASSTOUW] = {.fun = unary, .txt = "stoui", .letter = 'w'},
133	[ASDTOL] = {.fun = unary, .txt = "dtosi", .letter = 'l'},
134	[ASDTOUL] = {.fun = unary, .txt = "dtoui", .letter = 'l'},
135	[ASDTOW] = {.fun = unary, .txt = "dtosi", .letter = 'w'},
136	[ASDTOUW] = {.fun = unary, .txt = "dtoui", .letter = 'w'},
137
138	[ASSWTOD] = {.fun = unary, .txt = "swtof", .letter = 'd'},
139	[ASUWTOD] = {.fun = unary, .txt = "uwtof", .letter = 'd'},
140	[ASSWTOS] = {.fun = unary, .txt = "swtof", .letter = 's'},
141	[ASUWTOS] = {.fun = unary, .txt = "uwtof", .letter = 's'},
142	[ASSLTOD] = {.fun = unary, .txt = "sltof", .letter = 'd'},
143	[ASULTOD] = {.fun = unary, .txt = "ultof", .letter = 'd'},
144	[ASSLTOS] = {.fun = unary, .txt = "sltof", .letter = 's'},
145	[ASULTOS] = {.fun = unary, .txt = "ultof", .letter = 's'},
146
147	[ASEXTS] = {.fun = unary, .txt = "exts", .letter = 'd'},
148	[ASTRUNCD] = {.fun = unary, .txt = "truncd", .letter = 's'},
149
150	[ASNEGL] = {.fun = unary, .txt = "neg", .letter ='l'},
151	[ASNEGW] = {.fun = unary, .txt = "neg", .letter ='w'},
152	[ASNEGS] = {.fun = unary, .txt = "neg", .letter ='s'},
153	[ASNEGD] = {.fun = unary, .txt = "neg", .letter ='d'},
154
155	[ASBRANCH] = {.fun = branch},
156	[ASJMP]  = {.fun = jmp},
157	[ASRET]  = {.fun = ret},
158	[ASCALL] = {.fun = call},
159	[ASCALLE] = {.fun = ecall, .txt = ")"},
160	[ASCALLEX] = {.fun = ecall, .txt = ", ...)"},
161	[ASPAR] = {.fun = param, .txt = "%s %s, "},
162	[ASPARE] = {.fun = param, .txt = "%s %s"},
163	[ASALLOC] = {.fun = asalloc},
164	[ASFORM] = {.fun = form2local},
165
166	[ASVSTAR] = {.fun = vastart},
167	[ASVARG] = {.fun = vaarg},
168};
169
170static char buff[ADDR_LEN];
171/*
172 * : is for user-defined Aggregate Types
173 * $ is for globals (represented by a pointer)
174 * % is for function-scope temporaries
175 * @ is for block labels
176 */
177static char
178sigil(Symbol *sym)
179{
180	switch (sym->kind) {
181	case SEXTRN:
182	case SGLOB:
183	case SPRIV:
184	case SLOCAL:
185		return '$';
186	case SAUTO:
187	case STMP:
188		return '%';
189	case SLABEL:
190		return '@';
191	default:
192		abort();
193	}
194}
195
196static char *
197symname(Symbol *sym)
198{
199	char c = sigil(sym);
200
201	if (sym->name) {
202		switch (sym->kind) {
203		case SEXTRN:
204		case SGLOB:
205			sprintf(buff, "%c%s", c, sym->name);
206			return buff;
207		case SLOCAL:
208		case SPRIV:
209		case SAUTO:
210			sprintf(buff, "%c%s.L%u", c, sym->name, sym->id);
211			return buff;
212		default:
213			abort();
214		}
215	}
216	sprintf(buff, "%c.L%u", c, sym->numid);
217
218	return buff;
219}
220
221static void
222emitconst(Node *np)
223{
224	switch (np->type.size) {
225	case 1:
226		printf("%d", (int) np->u.i & 0xFF);
227		break;
228	case 2:
229		printf("%d", (int) np->u.i & 0xFFFF);
230		break;
231	case 4:
232		printf("%ld", (long) np->u.i & 0xFFFFFFFF);
233		break;
234	case 8:
235			printf("%lld", (long long) np->u.i);
236			break;
237	default:
238		abort();
239	}
240}
241
242static void
243emittree(Node *np)
244{
245	if (!np)
246		return;
247
248	switch (np->op) {
249	case OSTRING:
250		pprint(np->u.s);
251		free(np->u.s);
252		np->u.s = NULL;
253		break;
254	case OCONST:
255		emitconst(np);
256		break;
257	case OADDR:
258		emittree(np->left);
259		break;
260	case OMEM:
261		fputs(symname(np->u.sym), stdout);
262		break;
263	default:
264		emittree(np->left);
265		printf(" %c ", np->op);
266		emittree(np->right);
267		break;
268	}
269}
270
271static char *
272size2asm(Type *tp)
273{
274        static char spec[ADDR_LEN];
275
276	if (tp->flags & STRF) {
277		return "b";
278	} else if (tp->flags & INTF) {
279		switch (tp->size) {
280		case 1:
281			return "b";
282		case 2:
283			return "h";
284		case 4:
285			return "w";
286		case 8:
287			return "l";
288		}
289	} else if (tp->flags & FLOATF) {
290		if (tp->size == 4)
291			return "s";
292		else if (tp->size == 8)
293			return "d";
294	}
295
296	abort();
297}
298
299void
300defglobal(Symbol *sym)
301{
302	Type *tp = &sym->type;
303
304	if (sym->kind == SEXTRN)
305		return;
306	if (sym->kind == SGLOB)
307		fputs("export ", stdout);
308	if ((tp->flags & INITF) == 0)
309		fputs("common ", stdout);
310
311	printf("data %s = align %d {\n",
312	       symname(sym),
313	       tp->align);
314	if ((tp->flags & INITF) == 0)
315		printf("\tz\t%lu\n}\n", tp->size);
316}
317
318void
319defpar(Symbol *sym)
320{
321	if (sym->kind == SREG)
322		sym->kind = SAUTO;
323	sym->type.flags |= PARF;
324}
325
326void
327defvar(Symbol *sym)
328{
329	if (sym->kind == SREG)
330		sym->kind = SAUTO;
331}
332
333void
334data(Node *np)
335{
336	printf("\t%s\t", size2asm(&np->type));
337	emittree(np);
338	putchar(',');
339	putchar('\n');
340}
341
342static char *
343size2stack(Type *tp)
344{
345	static char spec[ADDR_LEN];
346
347	if (tp->flags & INTF) {
348		switch (tp->size) {
349		case 1:
350		case 2:
351		case 4:
352			return "w";
353		case 8:
354			return "l";
355		}
356	} else if (tp->flags & FLOATF) {
357		if (tp->size == 4)
358			return "s";
359		else if (tp->size == 8)
360			return "d";
361	} else if (tp->flags & (ARRF|AGGRF)) {
362		sprintf(spec, ":.%u", tp->id);
363		return spec;
364	} else if (tp->size == 0) {
365		return "w";
366	}
367	abort();
368}
369
370void
371deftype(Type *tp)
372{
373	printf("type :.%u = align %d { %lu }\n",
374	       tp->id, tp->align, tp->size);
375}
376
377static void
378getbblocks(void)
379{
380	Inst *i;
381
382	if (!prog)
383		return;
384
385	prog->flags |= BBENTRY;
386	for (pc = prog; pc; pc = pc->next) {
387		switch (pc->op) {
388		case ASBRANCH:
389			i = pc->from2.u.sym->u.inst;
390			i->flags |= BBENTRY;
391		case ASJMP:
392			i = pc->from1.u.sym->u.inst;
393			i->flags |= BBENTRY;
394		case ASRET:
395			if (pc->next)
396				pc->next->flags |= BBENTRY;
397			break;
398		}
399	}
400}
401
402void
403writeout(void)
404{
405	Symbol *p;
406	Type *tp;
407	char *sep;
408	int haslabel = 0;
409
410	getbblocks();
411
412	if (curfun->kind == SGLOB)
413		fputs("export ", stdout);
414	printf("function ");
415	if (curfun->rtype.size > 0)
416		printf("%s ", size2stack(&curfun->rtype));
417	printf("%s(", symname(curfun));
418
419	/* declare formal parameters */
420	sep = "";
421	for (p = locals; p; p = p->next) {
422		if ((p->type.flags & PARF) == 0)
423			continue;
424		printf("%s%s %s%s",
425		       sep, size2stack(&p->type),
426		       symname(p),
427		       (p->type.flags & AGGRF) ? "" : ".val");
428		sep = ",";
429	}
430	printf("%s)\n{\n@%s.body\n",
431	       (curfun->type.flags&ELLIPS) ? ", ..." : "",
432	       curfun->name);
433
434	/* emit assembler instructions */
435	for (pc = prog; pc; pc = pc->next) {
436		if (pc->label) {
437			haslabel = 1;
438			printf("%s\n", symname(pc->label));
439		}
440		if (pc->op == ASLABEL)
441			continue;
442		if (pc->flags&BBENTRY && !haslabel)
443			printf("%s\n", symname(newlabel()));
444		(*optbl[pc->op].fun)();
445		if (!pc->label)
446			haslabel = 0;
447	}
448
449	puts("}");
450}
451
452static char *
453addr2txt(Addr *a)
454{
455	switch (a->kind) {
456	case SCONST:
457		sprintf(buff, "%llu", (unsigned long long) a->u.i);
458		return buff;
459	case SAUTO:
460	case SLABEL:
461	case STMP:
462	case SGLOB:
463	case SEXTRN:
464	case SPRIV:
465	case SLOCAL:
466		return symname(a->u.sym);
467	default:
468		abort();
469	}
470}
471
472static void
473binary(void)
474{
475	struct opdata *p = &optbl[pc->op];
476	char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN];
477
478	strcpy(to, addr2txt(&pc->to));
479	strcpy(from1, addr2txt(&pc->from1));
480	strcpy(from2, addr2txt(&pc->from2));
481	printf("\t%s =%c\t%s\t%s,%s\n", to, p->letter, p->txt, from1, from2);
482}
483
484static void
485blit(void)
486{
487	Type *tp = &pc->from2.u.sym->type;
488	char to[ADDR_LEN], from[ADDR_LEN];
489
490	strcpy(to, addr2txt(&pc->to));
491	strcpy(from, addr2txt(&pc->from1));
492	printf("\t\tblit\t%s,%s,%lu\n", from, to, tp->size);
493}
494
495static void
496store(void)
497{
498	struct opdata *p = &optbl[pc->op];
499	char to[ADDR_LEN], from[ADDR_LEN];
500
501	strcpy(to, addr2txt(&pc->to));
502	strcpy(from, addr2txt(&pc->from1));
503	printf("\t\t%s%c\t%s,%s\n", p->txt, p->letter, from, to);
504}
505
506static void
507unary(void)
508{
509	struct opdata *p = &optbl[pc->op];
510	char to[ADDR_LEN], from[ADDR_LEN];
511
512	strcpy(to, addr2txt(&pc->to));
513	strcpy(from, addr2txt(&pc->from1));
514	printf("\t%s =%c\t%s\t%s\n", to, p->letter, p->txt, from);
515}
516
517static void
518call(void)
519{
520	char to[ADDR_LEN], from[ADDR_LEN];
521	Symbol *sym = pc->to.u.sym;
522
523	strcpy(to, addr2txt(&pc->to));
524	strcpy(from, addr2txt(&pc->from1));
525	if (sym->type.size > 0)
526		printf("\t%s =%s", to, size2stack(&sym->type));
527	printf("\tcall\t%s(", from);
528}
529
530static void
531param(void)
532{
533	Symbol *sym = pc->from2.u.sym;
534
535	printf(optbl[pc->op].txt,
536	       size2stack(&sym->type), addr2txt(&pc->from1));
537}
538
539static void
540ecall(void)
541{
542	struct opdata *p = &optbl[pc->op];
543
544	puts(p->txt);
545}
546
547static void
548ret(void)
549{
550	if (pc->from1.kind == SNONE)
551		puts("\t\tret");
552	else
553		printf("\t\tret\t%s\n", addr2txt(&pc->from1));
554}
555
556static void
557jmp(void)
558{
559	printf("\t\tjmp\t%s\n", addr2txt(&pc->from1));
560}
561
562static void
563branch(void)
564{
565	char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN];
566
567	strcpy(to, addr2txt(&pc->to));
568	strcpy(from1, addr2txt(&pc->from1));
569	strcpy(from2, addr2txt(&pc->from2));
570	printf("\t\tjnz\t%s,%s,%s\n", to, from1, from2);
571}
572
573static void
574vastart(void)
575{
576	printf("\t\tvastart %s\n", addr2txt(&pc->from1));
577}
578
579static void
580vaarg(void)
581{
582	Symbol *sym = pc->to.u.sym;
583	Type *tp = &sym->type;
584	char to[ADDR_LEN], from[ADDR_LEN];
585
586	strcpy(to, addr2txt(&pc->to));
587	strcpy(from, addr2txt(&pc->from1));
588	printf("\t\t%s =%s vaarg %s\n", to, size2asm(tp), from);
589}
590
591static void
592asalloc(void)
593{
594	Symbol *sym = pc->to.u.sym;
595	Type *tp = &sym->type;
596	extern Type ptrtype;
597
598	printf("\t%s =%s\talloc%d\t%lu\n",
599	       symname(sym), size2asm(&ptrtype), tp->align+3 & ~3, tp->size);
600}
601
602static void
603form2local(void)
604{
605	Symbol *sym = pc->to.u.sym;
606	Type *tp = &sym->type;
607	char *name = symname(sym);
608
609	printf("\t\tstore%s\t%s.val,%s\n", size2asm(tp), name, name);
610}
611
612void
613endinit(void)
614{
615	puts("}");
616}