416 lines
		
	
	
	
		
			7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			416 lines
		
	
	
	
		
			7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* $Id$ */
 | 
						|
/*
 | 
						|
 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | 
						|
 * See the copyright notice in the ACK home directory, in the file "Copyright".
 | 
						|
 */
 | 
						|
/*  S H O W . C  */
 | 
						|
 | 
						|
/* This program can be used to make the output of the 'cf' pass
 | 
						|
 * human readable. It will display either the procedure table,
 | 
						|
 * the datablock table, the basic block table or the EM text,
 | 
						|
 * depending on the flag that is passed as first argument.
 | 
						|
 */
 | 
						|
 | 
						|
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <em_spec.h>
 | 
						|
#include <em_pseu.h>
 | 
						|
#include "types.h"
 | 
						|
#include "def.h"
 | 
						|
#include "global.h"
 | 
						|
 | 
						|
 | 
						|
#define BMASK 0377
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
#define space1()	printf("	")
 | 
						|
char format[] = "	%-11s%d\n";
 | 
						|
char lformat[] = "	%-11s%ld\n";
 | 
						|
char sformat[] = "	%-10s%s\n";
 | 
						|
char dformat[] = "		%-11s%d\n";
 | 
						|
char oformat[] = "		%-11s%ld\n";
 | 
						|
 | 
						|
 | 
						|
 | 
						|
FILE *f;	/* input file */
 | 
						|
 | 
						|
 | 
						|
#define getbyte()	getc(f)
 | 
						|
 | 
						|
short getshort()
 | 
						|
{
 | 
						|
	register n;
 | 
						|
 | 
						|
	n = getbyte();
 | 
						|
	n |= getbyte() << 8;
 | 
						|
	return n;
 | 
						|
}
 | 
						|
 | 
						|
offset getoff()
 | 
						|
{
 | 
						|
	register offset n;
 | 
						|
 | 
						|
	n = (unsigned) getshort();
 | 
						|
	n |= ((offset) getshort() ) << 16;
 | 
						|
	return n;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int getint()
 | 
						|
{
 | 
						|
	/* Read an integer from the input file. This routine is
 | 
						|
	 * only used when reading a bitvector-set. We expect  an
 | 
						|
	 * integer to be either a short or a long.
 | 
						|
	 */
 | 
						|
 | 
						|
	if (sizeof(int) == sizeof(short)) {
 | 
						|
		return getshort();
 | 
						|
	} else {
 | 
						|
		return getoff();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* VARARGS 1 */
 | 
						|
error(s,a) char *s,*a; {
 | 
						|
 | 
						|
	fprintf(stderr,"error");
 | 
						|
	fprintf(stderr,": ");
 | 
						|
	fprintf(stderr,s,a);
 | 
						|
	fprintf(stderr,"\n");
 | 
						|
	exit(-1);
 | 
						|
}
 | 
						|
 | 
						|
main(argc, argv)
 | 
						|
	int argc;
 | 
						|
	char *argv[];
 | 
						|
{
 | 
						|
	if (argc != 3 || argv[1][0] != '-') {
 | 
						|
		error("usage: %s -[ldpbc] filename",argv[0]);
 | 
						|
	}
 | 
						|
	if ((f = fopen(argv[2], "r")) == NULL) {
 | 
						|
		error("cannot open %s", argv[2]);
 | 
						|
	}
 | 
						|
	switch(argv[1][1]) {
 | 
						|
		case 'l':
 | 
						|
			showl();
 | 
						|
			break;
 | 
						|
		case 'd':
 | 
						|
			showd();
 | 
						|
			break;
 | 
						|
		case 'p':
 | 
						|
			showp();
 | 
						|
			break;
 | 
						|
		case 'b':
 | 
						|
			showb();
 | 
						|
			break;
 | 
						|
		case 'c':
 | 
						|
			showc();
 | 
						|
			break;
 | 
						|
		default:
 | 
						|
			error("bad flag");
 | 
						|
	}
 | 
						|
 | 
						|
	fclose(f);
 | 
						|
	exit(0);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
showcset()
 | 
						|
{
 | 
						|
	/* print a compact (bitvector) set */
 | 
						|
 | 
						|
	short size;
 | 
						|
	register short i,j;
 | 
						|
	int w, mask;
 | 
						|
 | 
						|
	size = getshort();
 | 
						|
	/* # significant bits in bitvector */
 | 
						|
	i = 1;
 | 
						|
	printf(" { ");
 | 
						|
	if (size == 0) {
 | 
						|
		printf("}\n");
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	for (;;) {
 | 
						|
		w = getint();
 | 
						|
		mask = 1 ;
 | 
						|
		for (j = 1; j <= sizeof(int)*8; j++) {
 | 
						|
			if (w & mask) {
 | 
						|
				printf("%d ",i);
 | 
						|
			}
 | 
						|
			if (i++ == size) {
 | 
						|
				printf ("}\n");
 | 
						|
				return;
 | 
						|
			}
 | 
						|
			mask <<=  1;
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
showp()
 | 
						|
{
 | 
						|
	byte b;
 | 
						|
	short n;
 | 
						|
	short all;
 | 
						|
	printf("total number of procs: %d\n\n",getshort());
 | 
						|
	all = getshort();
 | 
						|
	while (TRUE) {
 | 
						|
		n = getshort();
 | 
						|
		if (feof(f)) break;
 | 
						|
		printf("PROC\n");
 | 
						|
		printf(format,"id =",n);
 | 
						|
		printf(format,"flags1 =",b = getbyte());
 | 
						|
		if (b & PF_BODYSEEN) {
 | 
						|
			printf(format,"# labels =",getshort());
 | 
						|
			printf(lformat,"# locals =",getoff());
 | 
						|
			printf(lformat,"# formals =",getoff());
 | 
						|
			if (all == 1) {
 | 
						|
				printf("	changed ="); showcset();
 | 
						|
				printf(format,"c_flags =",getshort());
 | 
						|
				printf(format,"u_flags =",getshort());
 | 
						|
				printf("	calling ="); showcset();
 | 
						|
			}
 | 
						|
		} else {
 | 
						|
			printf("	body not available\n");
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
char *pseudo[5] = {"hol", "bss", "rom", "con", "unknown" };
 | 
						|
 | 
						|
showd()
 | 
						|
{
 | 
						|
	short n;
 | 
						|
	printf("total number of objects: %d\n\n",getshort());
 | 
						|
	while (TRUE) {
 | 
						|
		n = getbyte();
 | 
						|
		if (feof(f)) break;
 | 
						|
		switch(n) {
 | 
						|
			case MARK_DBLOCK:
 | 
						|
				printf("DBLOCK\n");
 | 
						|
				printf(format,"id =",getshort());
 | 
						|
				printf(sformat,"pseudo =",
 | 
						|
					pseudo[(short) getbyte()]);
 | 
						|
				printf(lformat,"size =",getoff());
 | 
						|
				printf(format,"fragment =",getshort());
 | 
						|
				printf(format,"flags1 =",
 | 
						|
					(short) getbyte());
 | 
						|
				break;
 | 
						|
			case MARK_OBJ:
 | 
						|
				printf("	OBJ\n");
 | 
						|
				space1();
 | 
						|
				printf(format,"id =",getshort());
 | 
						|
				space1();
 | 
						|
				printf(lformat,"size =",getoff());
 | 
						|
				space1();
 | 
						|
				printf(lformat,"offset =",getoff());
 | 
						|
				break;
 | 
						|
			case MARK_ARG:
 | 
						|
				printf("	VALUE\n");
 | 
						|
				space1();
 | 
						|
				printf(lformat,"offset =",getoff());
 | 
						|
				break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* The mnemonics of the EM instructions and pseudos */
 | 
						|
 | 
						|
 | 
						|
extern char em_mnem[];
 | 
						|
extern char em_pseu[];
 | 
						|
char lab_mnem[] = "instrlab";
 | 
						|
char sym_mnem[] = "datalab";
 | 
						|
 | 
						|
showinstr()
 | 
						|
{
 | 
						|
	short instr;
 | 
						|
	char *s;
 | 
						|
 | 
						|
	instr = (short) getbyte();
 | 
						|
	if (feof(f)) return FALSE;
 | 
						|
	if (instr >= sp_fmnem && instr <= sp_lmnem) {
 | 
						|
		s = &(em_mnem[(instr-sp_fmnem) *4]);
 | 
						|
	} else {
 | 
						|
		if (instr == op_lab) {
 | 
						|
			s = lab_mnem;
 | 
						|
		} else {
 | 
						|
			if (instr == ps_sym) {
 | 
						|
				s = sym_mnem;
 | 
						|
			} else {
 | 
						|
				s = &(em_pseu[(instr-sp_fpseu)*4]);
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	printf("%s",s);
 | 
						|
	switch((short) getbyte()) {
 | 
						|
		case OPSHORT:
 | 
						|
		case OPOBJECT:
 | 
						|
			printf(" %d", getshort());
 | 
						|
			break;
 | 
						|
		case OPPROC:
 | 
						|
			printf(" $%d",getshort());
 | 
						|
			break;
 | 
						|
		case OPINSTRLAB:
 | 
						|
			printf(" *%d",getshort());
 | 
						|
			break;
 | 
						|
		case OPOFFSET:
 | 
						|
			printf(" %ld", getoff());
 | 
						|
			break;
 | 
						|
		case OPLIST:
 | 
						|
			arglist();
 | 
						|
			break;
 | 
						|
	}
 | 
						|
	printf("\n");
 | 
						|
	return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
showl()
 | 
						|
{
 | 
						|
	while (showinstr());
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
arglist()
 | 
						|
{
 | 
						|
	short length;
 | 
						|
	for (;;) {
 | 
						|
		switch((short) getbyte()) {
 | 
						|
			case ARGOBJECT:
 | 
						|
				printf(" %d", getshort());
 | 
						|
				break;
 | 
						|
			case ARGPROC:
 | 
						|
				printf(" $%d",getshort());
 | 
						|
				break;
 | 
						|
			case ARGINSTRLAB:
 | 
						|
				printf(" *%d",getshort());
 | 
						|
				break;
 | 
						|
			case ARGOFF:
 | 
						|
				printf(" %ld", getoff());
 | 
						|
				break;
 | 
						|
			case ARGICN:
 | 
						|
			case ARGUCN:
 | 
						|
			case ARGFCN:
 | 
						|
				printf(" %d",getshort());
 | 
						|
				/* Fall through !! */
 | 
						|
			case ARGSTRING:
 | 
						|
				length = getshort();
 | 
						|
				putchar(' ');
 | 
						|
				putchar('"');
 | 
						|
				while (length--) {
 | 
						|
					putchar(getbyte());
 | 
						|
				}
 | 
						|
				putchar('"');
 | 
						|
				break;
 | 
						|
			case ARGCEND:
 | 
						|
				return;
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
showlset()
 | 
						|
{
 | 
						|
	register short x;
 | 
						|
 | 
						|
	printf("{ ");
 | 
						|
	while (x = getshort()) {
 | 
						|
		printf("%d ",x);
 | 
						|
	}
 | 
						|
	printf("}\n");
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
showb()
 | 
						|
{
 | 
						|
	/* basic block file */
 | 
						|
 | 
						|
	short n,m;
 | 
						|
 | 
						|
	while (TRUE) {
 | 
						|
		n = getshort();
 | 
						|
		if (feof(f)) break;
 | 
						|
		if (n == 0) {
 | 
						|
			printf("Declaration Unit:\n");
 | 
						|
			printf(dformat,"#instrs =",getshort());
 | 
						|
			printf("\n");
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
		printf("Control Flow Graph:\n");
 | 
						|
		printf("number of basic blocks: %d\n",n);
 | 
						|
		m = getshort(); /* #loops */
 | 
						|
		while (n--) {
 | 
						|
			printf("	BASIC BLOCK\n");
 | 
						|
			printf(dformat,"id =",getshort());
 | 
						|
			printf(dformat,"# instrs =",getshort());
 | 
						|
			printf("		succ =");
 | 
						|
			showlset();
 | 
						|
			printf("		pred =");
 | 
						|
			showlset();
 | 
						|
			printf(dformat,"idom =",getshort());
 | 
						|
			printf("		loops =");
 | 
						|
			showlset();
 | 
						|
			printf(dformat,"flags =",getshort());
 | 
						|
		}
 | 
						|
		printf("number of loops: %d\n",m);
 | 
						|
		while (m--) {
 | 
						|
			printf("	LOOP\n");
 | 
						|
			printf(dformat,"id =",getshort());
 | 
						|
			printf(dformat,"level =",getshort());
 | 
						|
			printf(dformat,"entry =",getshort());
 | 
						|
			printf(dformat,"end =",getshort());
 | 
						|
		}
 | 
						|
		printf("\n");
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
showc()
 | 
						|
{
 | 
						|
	int n,m,cnt,t;
 | 
						|
 | 
						|
	cnt = 1;
 | 
						|
	while(TRUE) {
 | 
						|
		t = getshort();
 | 
						|
		if (feof(f)) break;
 | 
						|
		printf("CALL %d\n",cnt++);
 | 
						|
		printf(format,"nestlevel =",t);
 | 
						|
		printf(format,"calling p. =",getshort());
 | 
						|
		printf(format,"call_id =",getshort());
 | 
						|
		printf(format,"called p. =",getshort());
 | 
						|
		printf(format,"looplevel =",getbyte());
 | 
						|
		printf(format,"flags =",getbyte());
 | 
						|
		printf(format,"ratio =",getshort());
 | 
						|
		printf("	actuals:");
 | 
						|
		n = getshort();
 | 
						|
		if (n == 0) {
 | 
						|
			printf("  ---\n");
 | 
						|
		} else {
 | 
						|
			while (n--) {
 | 
						|
				printf("\n");
 | 
						|
				m = getshort();
 | 
						|
				printf(oformat,"size =",getoff());
 | 
						|
				printf(dformat,"inl =",getbyte());
 | 
						|
				while (m--) {
 | 
						|
					printf("		");
 | 
						|
					showinstr();
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 |