⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gen.c

📁 window下的c编译器。
💻 C
📖 第 1 页 / 共 3 页
字号:
#include "c.h"
extern Symbol intreg[];
//#define DODEBUG
#define NORMAL_REG_ORDER
#define readsreg(p) \
	(generic((p)->op)==INDIR && (p)->kids[0]->op==VREG+P)
#define setsrc(d) ((d) && (d)->x.regnode && \
	(d)->x.regnode->set == src->x.regnode->set && \
	(d)->x.regnode->mask&src->x.regnode->mask)

#define relink(a, b) ((b)->x.prev = (a), (a)->x.next = (b))

static Symbol   askfixedreg     ARGS((Symbol));
static Symbol   askreg          ARGS((Symbol, unsigned*));
static void     blkunroll       ARGS((int, int, int, int, int, int, int[]));
static void     docall          ARGS((Node));
static void     dumpcover       ARGS((Node, int, int));
#ifdef DODEBUG
static void     dumpregs        ARGS((char *, char *, char *,char *));
#endif
static void     dumprule        ARGS((int));
void     dumptree        ARGS((Node,int));
unsigned	emitasm		ARGS((Node, int));
static void     genreload       ARGS((Node, Symbol, int));
static void     genspill        ARGS((Symbol, Node, Symbol));
static Symbol   getreg          ARGS((Symbol, unsigned*, Node,int));
static int      getrule         ARGS((Node, int));
void     linearize       ARGS((Node, Node));
int      moveself        ARGS((Node));
static void     prelabel        ARGS((Node));
static Node*    prune           ARGS((Node, Node*));
static void     putreg          ARGS((Symbol));
static void     ralloc          ARGS((Node));
static void     reduce          ARGS((Node, int));
static int      reprune         ARGS((Node*, int, int, Node));
int      requate         ARGS((Node));
static Node     reuse           ARGS((Node, int));
static void     rewrite         ARGS((Node));
static Symbol   spillee         ARGS((Symbol, Node));
static void     spillr          ARGS((Symbol, Node));
static int      trashes         ARGS((Node, Node));
static int      uses            ARGS((Node, unsigned));

int offset;

int maxoffset;

int framesize;
int argoffset;

int maxargoffset;

int dalign, salign;
int bflag = 0;  /* omit */
int dflag = 0;

int swap;

static int unsafe=1;

unsigned (*emitter) ARGS((Node, int)) = emitasm;
static char NeedsReg[] = {
	0,                      /* unused */
	1,                      /* CNST */
	0, 0,                   /* ARG ASGN */
	1,                      /* INDIR  */
	1, 1, 1, 1,             /* CVC CVD CVF CVI */
	1, 1, 1, 1,             /* CVP CVS CVU NEG */
	1,                      /* CALL */
	1,                      /* LOAD */
	0,                      /* RET */
	1, 1, 1,                /* ADDRG ADDRF ADDRL */
	1, 1, 1, 1, 1,          /* ADD SUB LSH MOD RSH */
	1, 1, 1, 1,             /* BAND BCOM BOR BXOR */
	1, 1,                   /* DIV MUL */
	0, 0, 0, 0, 0, 0,       /* EQ GE GT LE LT NE */
	0, 0,                   /* JUMP LABEL   */
	1
};
Symbol rmap[16];
Node head;

unsigned freemask[2];
unsigned usedmask[2];
unsigned tmask[2];
unsigned vmask[2];
Symbol mkreg(char *fmt,int n,int mask,int set)
{
	Symbol p;

	NEW0(p, PERM);
	p->name = fmt+1;
	p->x.name = stringf(fmt, n);
	NEW0(p->x.regnode, PERM);
	p->x.regnode->number = (short)n;
	p->x.regnode->mask = mask<<n;
	p->x.regnode->set = (short)set;
	return p;
}
Symbol mkwildcard(Symbol *syms)
{
	Symbol p;

	NEW0(p, PERM);
	p->x.name = "wildcard";
	p->x.wildcard = syms;
	return p;
}
void mkauto(Symbol p)
{
	assert(p->sclass == AUTO);
	offset = roundup(offset + p->type->size, p->type->align);
	p->x.offset = -offset;
	if (hasExceptions)
		p->x.offset -= 24;
	if (glevel > 2)
		p->x.offset -= 12;
	p->x.name = stringd(p->x.offset);
}
void blockbeg(Env *e)
{
	e->offset = offset;
	e->freemask[IREG] = freemask[IREG];
	e->freemask[FREG] = freemask[FREG];
}
void blockend(Env *e)
{
	if (offset > maxoffset)
		maxoffset = offset;
	offset = e->offset;
	freemask[IREG] = e->freemask[IREG];
	freemask[FREG] = e->freemask[FREG];
}
int mkactual(int align,int size)
{
	int n = roundup(argoffset, align);

	argoffset = n + size;
	return n;
}
static void docall(Node p)
{
	FunctionHasCalls = 1;
	p->syms[0] = intconst(argoffset);
	if (argoffset > maxargoffset)
		maxargoffset = argoffset;
	argoffset = 0;
}
void blkcopy(int dreg,int doff,int sreg,int soff,int size,int tmp[])
{
	assert(size >= 0);
	if (size == 0)
		return;
	else if (size <= 2)
		blkunroll(size, dreg, doff, sreg, soff, size, tmp);
	else if (size == 3) {
		blkunroll(2, dreg, doff,   sreg, soff,   2, tmp);
		blkunroll(1, dreg, doff+2, sreg, soff+2, 1, tmp);
	}
	else if (size <= 16) {
		blkunroll(4, dreg, doff, sreg, soff, size&~3, tmp);
		blkcopy(dreg, doff+(size&~3),
					sreg, soff+(size&~3), size&3, tmp);
	}
	else
		(*IR->x.blkloop)(dreg, doff, sreg, soff, size, tmp);
}
static void blkunroll(int k,int dreg,int doff,int sreg,int soff,int size,int tmp[])
{
	int i;

	assert(IR->x.max_unaligned_load);
	if (k > IR->x.max_unaligned_load
	&& (k > salign || k > dalign))
		k = IR->x.max_unaligned_load;
	for (i = 0; i+k < size; i += 2*k) {
		(*IR->x.blkfetch)(k, soff+i,   sreg, tmp[0]);
		(*IR->x.blkfetch)(k, soff+i+k, sreg, tmp[1]);
		(*IR->x.blkstore)(k, doff+i,   dreg, tmp[0]);
		(*IR->x.blkstore)(k, doff+i+k, dreg, tmp[1]);
	}
	if (i < size) {
		(*IR->x.blkfetch)(k, i+soff, sreg, tmp[0]);
		(*IR->x.blkstore)(k, i+doff, dreg, tmp[0]);
	}
}
void parseflags(int argc,char *argv[])
{
	int i;

	for (i = 0; i < argc; i++)
		if (strcmp(argv[i], "-d") == 0)
			dflag = 1;
		else if (strcmp(argv[i], "-b") == 0)	/* omit */
			bflag = 1;			/* omit */
}
/*------------------------------------------------------------------------
 Procedure:     getrule ID:1
 Purpose:       This function just encapsulates the call to the
				interface rule function. 14.3.382
 Input:
 Output:
 Errors:
------------------------------------------------------------------------*/
static int getrule(Node p,int nt)
{
	int rulenum;

	assert(p);
	rulenum = (*IR->x._rule)(p->x.state, nt);
	if (rulenum == 0) {
		assert(0);
	}
	return rulenum;
}
static void reduce(Node p,int nt)
{
	int rulenum, i;
	short *nts;
	Node kids[10];

	p = reuse(p, nt);
#ifdef PURIFY
	rulenum = getrule(p, nt);
#else
	rulenum = (*IR->x._rule)(p->x.state, nt);
#endif
	nts = IR->x._nts[rulenum];
	p->x.rulenum = rulenum;
	(*IR->x._kids)(p, rulenum, kids);
	for (i = 0; nts[i]; i++)
		reduce(kids[i], nts[i]);
	if (IR->x._isinstruction[rulenum]) {
		assert(p->x.inst == 0 || p->x.inst == nt);
		p->x.inst = (short)nt;
		if (p->syms[RX] && p->syms[RX]->temporary) {
#ifdef DODEBUG
			fprint(2, "(using %s)\n", p->syms[RX]->name);
#endif
			p->syms[RX]->x.usecount++;
		}
	}
}
/*------------------------------------------------------------------------
 Procedure:     reuse ID:1
 Purpose:       The call to reuse sees if the reduction of node p using
				nonterminal nt uses a 'bonus match'. If so, it returns
				the common subexpression instead of p. The objective is
				to reprocess the common subexpression and ignore the
				temporary. It collaborates with reduce to recalculate
				expressions that are cheaper to recalculate than to
				store into a register.14.3.383
 Input:
 Output:
 Errors:
------------------------------------------------------------------------*/
static Node reuse(Node p,int nt)
{
	struct _state {
		short cost[1];
	};
	Symbol r = p->syms[RX];

	if (generic(p->op) == INDIR && p->kids[0]->op == VREG+P
	&& r->u.t.cse && p->x.mayrecalc
	&& ((struct _state*)r->u.t.cse->x.state)->cost[nt] == 0)
		return r->u.t.cse;
	else
		return p;
}

int mayrecalc(Node p)
{
	Node q;

	assert(p && p->syms[RX]);
	if (!p->syms[RX]->u.t.cse)
		return 0;
	for (q = head; q && q->x.listed; q = q->link)
		if (generic(q->op) == ASGN
		&& trashes(q->kids[0], p->syms[RX]->u.t.cse))
			return 0;
	p->x.mayrecalc = 1;
	return 1;
}
static int trashes(Node p,Node q)
{
	assert(p);
	if (!q)
		return 0;
	/*
	This read before syms[0]. It should be syms[RX] in my opinion. I leave both
	*/
	else if (p->op == q->op &&
		(p->syms[RX] == q->syms[RX] || p->syms[0] == q->syms[0]))
		return 1;
	else
		return trashes(p, q->kids[0])
			|| trashes(p, q->kids[1]);
}
static Node *prune(Node p,Node pp[])
{
	if (p == NULL)
		return pp;
#if 0 /* here I have a problem. The origianl sources didn't make this assertion. Where does this come from? */
	if(p->x.kids[2] != NULL) {
		assert(0);
	}
#endif
	p->x.kids[0] = p->x.kids[1] = p->x.kids[2] = NULL;
	if (p->x.inst == 0)
		return prune(p->kids[1], prune(p->kids[0], pp));
	else if (p->syms[RX] && p->syms[RX]->temporary
	&& p->syms[RX]->x.usecount < 2) {
		p->x.inst = 0;
#ifdef DODEBUG
		fprint(2, "(clobbering %s)\n", p->syms[RX]->name);
#endif
		return prune(p->kids[1], prune(p->kids[0], pp));
	}
	else {
		prune(p->kids[1], prune(p->kids[0], &p->x.kids[0]));
		*pp = p;
		return pp + 1;
	}
}

#define ck(i) return (i) ? 0 : LBURG_MAX

int range(Node p,int lo,int hi)
{
	Symbol s = p->syms[0];

	switch (p->op) {
	case ADDRFP: ck(s->x.offset >= lo && s->x.offset <= hi);
	case ADDRLP: ck(s->x.offset >= lo && s->x.offset <= hi);
	case CNSTC:  ck(s->u.c.v.sc >= lo && s->u.c.v.sc <= hi);
	case CNSTI:  ck(s->u.c.v.i  >= lo && s->u.c.v.i  <= hi);
	case CNSTS:  ck(s->u.c.v.ss >= lo && s->u.c.v.ss <= hi);
	case CNSTU:  ck(s->u.c.v.u  >= (unsigned)lo && s->u.c.v.u  <= (unsigned)hi);
	case CNSTP:  ck(s->u.c.v.p  == 0  && lo <= 0 && hi >= 0);
	}
	return LBURG_MAX;
}
void dumptree(Node p,int level)
{
	fprint(2, "%s(", IR->x._opname[p->op]);
	if (IR->x._arity[p->op] == 0 && p->syms[0])
		fprint(2, "%s", p->syms[0]->name);
	else if (IR->x._arity[p->op] == 1)
		dumptree(p->kids[0],level+1);
	else if (IR->x._arity[p->op] == 2) {
		dumptree(p->kids[0],level+1);
		fprint(2, ", ");
		dumptree(p->kids[1],level+1);
	}
	fprint(2, ")");
}
void ildumptree(Node p,int level)
{
	fprintf(ilFile, "%s(", IR->x._opname[p->op]);
	if (IR->x._arity[p->op] == 0 && p->syms[0]) {
		if (p->syms[0]->name == NULL)
			fprintf(ilFile,"%s",p->syms[0]->x.name);
		else
			fprintf(ilFile, "%s", p->syms[0]->name);
	}
	else if (IR->x._arity[p->op] == 1)
		ildumptree(p->kids[0],level+1);
	else if (IR->x._arity[p->op] == 2) {
		int i;
		fprintf(ilFile,"\n");
		for (i=0; i<=level;i++) fprintf(ilFile,"     ");
		ildumptree(p->kids[0],level+1);
		fprintf(ilFile, ",\n");
		for(i=0; i<=level;i++) fprintf(ilFile,"     ");
		ildumptree(p->kids[1],level+1);
	}
	fprintf(ilFile, ")");
}
static void ildumprule(int rulenum)
{
	assert(rulenum);
	fprintf(ilFile, "%s / %s", IR->x._string[rulenum],
		IR->x._templates[rulenum]);
	if (!IR->x._isinstruction[rulenum])
		fprintf(ilFile, "\n");
}
void ildumpcover(Node p,int nt,int in)
{
	int rulenum, i;
	short *nts;
	Node kids[10];

	p = reuse(p, nt);
	rulenum = (*IR->x._rule)(p->x.state, nt);
	nts = IR->x._nts[rulenum];
	for (i = 0; i < in; i++)
		fprintf(ilFile, " ");
	ildumprule(rulenum);
	(*IR->x._kids)(p, rulenum, kids);
	for (i = 0; nts[i]; i++)
		ildumpcover(kids[i], nts[i], in+1);
}
#ifdef DODEBUG

static void dumpcover(Node p,int nt,int in)
{
	int rulenum, i;
	short *nts;
	Node kids[10];

	p = reuse(p, nt);
#ifdef PURIFY
	rulenum = getrule(p, nt);
#else
	rulenum = (*IR->x._rule)(p->x.state, nt);
#endif
	nts = IR->x._nts[rulenum];
	fprint(2, "dumpcover(%x) = ", p);
	for (i = 0; i < in; i++)
		fprint(2, " ");
	dumprule(rulenum);
	(*IR->x._kids)(p, rulenum, kids);
	for (i = 0; nts[i]; i++)
		dumpcover(kids[i], nts[i], in+1);
}

static void dumprule(int rulenum)
{
	assert(rulenum);
	fprint(2, "%s / %s", IR->x._string[rulenum],
		IR->x._templates[rulenum]);
	if (!IR->x._isinstruction[rulenum])
		fprint(2, "\n");
}
#endif /* DODEBUG */
/*------------------------------------------------------------------------
 Procedure:     emitasm ID:1
 Purpose:       Processes a partially linearized tree. List elements are
				the roots of subtrees for instructions. It traces the
				sub-instructions which correspond to  addressing modes
				and other calculations inside a logical instruction. The
				driver of emitasm, 'emit' ensures that this instructions
				are seen in the right order.
				It sets the x.emitted flag as it emits them. 14.6.392
 Input:
 Output:
 Errors:
------------------------------------------------------------------------*/
extern int hasAllocA;
int NeedsLineReset;
unsigned emitasm(Node p,int nt)
{
	int rulenum,booleanAsgn,genericOp;
	short *nts; /* Used only in a recursive call
				Contains the nonterminals for the rule's pattern */
	register char *fmt;
	Node kids[10];
	int isinstruction;
	char *oldbp;
	extern int cseg;
	int NeedsCallReset=0;
	char newfmt[40];

	p = reuse(p, nt);
#ifdef PURIFY
	rulenum = getrule(p, nt);
#else
	rulenum = (*IR->x._rule)(p->x.state, nt);
#endif
	nts = IR->x._nts[rulenum];
	fmt = IR->x._templates[rulenum];
	assert(fmt);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -