V10/cmd/lcomp/bb.c

Compare this file to the similar file:
Show the results in this format:

#define unsafe 1	/* pretend killing all but C is as good as killing
			 * all condition codes */
#ifdef unsafe
#define E	(C|K)
#else
#define E	K
#endif
#include "stdio.h"
#include "instr.c"
#include "ctype.h"
struct inst *index[128];

#define SBBLK	1	/* looking for the start of a basic block */
#define SINST	2	/* thinking about generating a tally */
#define SPRO	3	/* thinking about generating prolog code */
#define SMAYBE	4	/* seen _, thinking about SPRO */

FILE *outs, *fd, *outl;	/* outs goes to assembler, outl is for listing */
extern FILE *popen();
char line[256], fname[256];	/* file names must fit in fname */
char curfunc[256];
int lineno, lastline;
int cnt;
int state = SBBLK;
char *ptr, *curarg;
char curdir[256];

main(argc, argv)
char **argv;
{	int i;
	if(argc <= 1) {
		fprintf(stderr, "no files given\n");
		exit(1);
	}
	for(i = 0; insts[i].iname; i++)
		;
	for(; i >= 0; i--)
		index[insts[i].iname[0]] = insts + i;
	fd = popen("pwd", "r");
	for(i = 0; i < sizeof(curdir) && !feof(fd); i++)
		curdir[i] = getc(fd);
	curdir[i-2] = 0;	/* thisdir\n */
	fclose(fd);
	for(i = 1; i < argc; i++) {
		if(setfd(argv[i]))	/* fix fd, outs, outl */
			doarg();	/* do the work */
	}
	exit(0);
}

setfd(s)
char *s;
{	char outnams[24], outnaml[24];
	fname[0] = 0;
	cnt = 3;
	if(fd != NULL)
		fclose(fd);
	if(outs != NULL)
		fclose(outs);
	if(outl != NULL)
		fclose(outl);
	sprintf(outnams, "X%s", s);
	sprintf(outnaml, "%sL", s);
	lastline = lineno = 0;
	fd = fopen(s, "r");
	if(fd == NULL) {
		perror(s);
		return(0);
	}
	outs = fopen(outnams, "w");
	if(outs == NULL) {
		perror(outnams);
		return(0);
	}
	outl = fopen(outnaml, "w");
	if(outl == NULL) {
		perror(outnaml);
		return(0);
	}
	curarg = s;
	return(1);
}

doarg()
{	struct inst *x, *firstword();
	state = SBBLK;
	for(;;) {
		(void) fgets(line, sizeof(line), fd);
		if(feof(fd))
			break;
		for(ptr = line; isspace(*ptr); *ptr++)
			;
		if(*ptr == 0 || *ptr == '#')
			continue;
		testlabel();
		/* deal with symbol table info */
		if(*ptr == '.') {
			stab();
			fprintf(outs, "%s", ptr);
			continue;
		}
		if(*ptr == 0 || *ptr == '\n')
			continue;
		x = firstword();
		if(x == 0)
			continue;
		if(state == SPRO)
			prolog(x);
		if(state == SINST)
			tally(x);
		if(state == SBBLK && (x->type & JUMP))
			state = SINST;
		outinstr();
		if(x->type & BYTE)
			fixinstr(x);
		fprintf(outs, "%s", ptr);
	}
	finish();
}
/* unbelievable variability in sdb info */
stab()
{	char buf[128];
	int i, j, k;
	if(state == SMAYBE && strncmp(ptr, ".word", 5) == 0) {
		state = SPRO;
		return;
	}
	if((i = *(ptr + 1)) != 's' && i != 'f' && i != 'l')
		return;
	/* real compiler output */
	if(sscanf(ptr, ".stabs \"%[^\"]\", %o", buf, &i) == 2 && i == 0144)
		strcat(fname, buf);
	else if(sscanf(ptr, ".stabs \"%[^\"]\", 0x%x", buf, &i) == 2 && i == 0x64)
		strcat(fname, buf);
	else if(sscanf(ptr, ".stabd %o,%o,%o", &i, &j, &k) == 3 && i == 0104)
		lineno = k;
	else if(sscanf(ptr, ".stabd 0x%x,0,%d", &i, &k) == 2 && i == 0x44)
		lineno = k;
	/* pwb 3.0 */
	else if(sscanf(ptr, ".stab %[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%d",
		buf, buf+2, buf+4, buf+6, buf+8, buf+10, buf+12, buf+14, &i)
		== 9 && i == 144) {
			for(i = k = 0; buf[i] ; i++)
				if(buf[i] == '\'')
					buf[k++] = buf[++i];
			buf[k] = 0;
			strcat(fname, buf);
		}
	else if(sscanf(ptr, ".stab %[0,]%d,%d,%d", buf,&i, &j, &k) == 4
		&& i == 104)
		lineno = k;
	/* pwb 5.0 */
 	else if(sscanf(ptr," .file \"%[^\"]\"", buf) == 1)
		strcat(fname, buf);
 	else if(sscanf(ptr, " .ln %d",&k) == 1)
		lineno = k;
}

testlabel()
{	char *p;
again:
	for(p = ptr; *p; p++) {
		if(*p == ':')
			break;
		if(isalnum(*p) || *p == '_')
			continue;
		if(p > ptr && *p == '.')	/* f77 */
			continue;
		return;
	}
	if(*p == 0)
		return;
	*p++ = 0;	/* that is overwriting the : */
	fprintf(outs, "%s:\n", ptr);
	if(*ptr == '_') {
		state = SMAYBE;
		strcpy(curfunc, ptr);
	}
	else
		if(state != SPRO)
			state = SINST;
	for(ptr = p; isspace(*ptr); ptr++)
		;
	goto again;	/* L68:L70: ... */
}

struct inst *
firstword()
{	char buf[sizeof(line)], *p, *q;
	struct inst *x;
	for(p = buf, q = ptr; isalnum(*q); )
		*p++ = *q++;
	if(p == buf)
		return((struct inst *)0);
	*p = 0;
	for(x = index[buf[0]]; x && x->iname[0] == buf[0]; x++)
		if(strcmp(buf, x->iname) == 0)
			return(x);
	return(0);
}

tally(x)
struct inst *x;
{
	if(x->type & E)
		fprintf(outs, "incl locprof+%d\n", 4*cnt++);
	else {
		fprintf(outs, "movpsl -(sp)\n");
		fprintf(outs, "incl locprof+%d\n", 4*cnt++);
		fprintf(outs, "movw (sp)+,(sp)\n");
		fprintf(outs, "bicpsw $0xff\n");
		fprintf(outs, "bispsw (sp)+\n");
		/* thanks to kirk mckusick */
	}
	state = SBBLK;
}

outinstr()
{	int i;
	for(i = lastline + 1; i <= lineno; i++)
		fprintf(outl, "%d %s: %d\n", 4*(cnt - 1), fname, i);
	lastline = lineno;
	fprintf(outl, "%d %s", 4*(cnt - 1), ptr);
}

prolog(x)	/* no liveness test, presumes can't get here by jump */
struct inst *x;
{	int i;
	fprintf(outs, ".data\n");
	fprintf(outs, ".comm _proFptr,4\n");	/* the global chain */
	fprintf(outs, ".text\n");
	fprintf(outs, "tstl locprof+4\n");
	fprintf(outs, "bneq L%da\n", i = cnt);
	fprintf(outs, "movl _proFptr,locprof+4\n");
	fprintf(outs, "moval locprof,_proFptr\n");
	fprintf(outs, "L%da: incl locprof+%d\n", i, 4*cnt++);
	state = SBBLK;
	fprintf(outl, "%d %s: %s\n", 4*(cnt-1), fname, curfunc);
}

finish()
{	int i;
	fprintf(outs, ".data\n");
	fprintf(outs, "locprof: .long %d\n", cnt);
	fprintf(outs, ".long 0\n");
	fprintf(outs, ".long L%db\n", cnt);
	fprintf(outs, ".space %d\n", 4 * cnt);
	fprintf(outs, "L%db: .byte ", cnt);
	for(i = 0; curdir[i]; i++)
		fprintf(outs, "0x%x,", curdir[i]);
	fprintf(outs, "0x%x\n", '/');
	fprintf(outs, ".byte ");
	if(fname[0])
		for(i = 0; fname[i]; i++)
			fprintf(outs, "0x%x,", fname[i]);
	else
		for(i = 0; curarg[i]; i++)
			fprintf(outs, "0x%x,", curarg[i]);
	fprintf(outs, "0\n");
}

fixinstr(x)
struct inst *x;
{
	if(x->iname[0] == 'b')
		*ptr = 'j';	/* let assembler worry about branches */
	/* this is where the code for aob and sob goes */
}