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

📄 gen.c

📁 window下的c编译器。
💻 C
📖 第 1 页 / 共 3 页
字号:
#ifdef DODEBUG
	dumpregs("(freeing %s)\n", r->x.name, NULL,NULL);
#endif
}
static Symbol askfixedreg(Symbol s)
{
	Regnode r = s->x.regnode;
	int n = r->set;

	if (r->mask&~freemask[n])
		return NULL;
	else {
		freemask[n] &= ~r->mask;
		usedmask[n] |=  r->mask;
		return s;
	}
}
extern int clobbering;

static Symbol askreg(Symbol rs,unsigned rmask[])
{
	int i;
	Symbol r;

	if (rs->x.wildcard == NULL)
		return askfixedreg(rs);
	if (unsafe)
	for (i = 7; i >= 0; i--) {
		r = rs->x.wildcard[i];
		if (r != NULL
		&& !(r->x.regnode->mask&~rmask[r->x.regnode->set])
		&& askfixedreg(r)) {
			return r;
		}
	}
	else {
		r = rs->x.wildcard[0]; // EAX
		if (r != NULL
			&& !(r->x.regnode->mask&~rmask[r->x.regnode->set])
			&& askfixedreg(r))
			return r;
		r = rs->x.wildcard[2]; // EDX
		if (r != NULL
			&& !(r->x.regnode->mask&~rmask[r->x.regnode->set])
			&& askfixedreg(r))
				return r;
		r = rs->x.wildcard[1]; // ECX
		if (r != NULL
			&& !(r->x.regnode->mask&~rmask[r->x.regnode->set])
			&& askfixedreg(r))
			return r;
	/* It is better to start with the eax, ebx ecx, etc registers.
	This limits the number of unnecessary moves and makes esi edi
	available for further optimizations.
	*/
		for (i = 0; i < 32; i++) {
			Symbol r = rs->x.wildcard[i];
			if (r != NULL
			&& !(r->x.regnode->mask&~rmask[r->x.regnode->set])
			&& askfixedreg(r))
				return r;
		}
	}
	return NULL;
}

static Symbol getreg(Symbol s,unsigned mask[],Node p,int tmpflag)
{
	Symbol r;

	if (p->x.dangerousChildren)
		mask[0] &= ~1;

	if (OptimizeFlag == 0) {
		r = askreg(s,mask);
	}
	else {
		int saveMask = mask[0];
		if (p->x.clobbersWhich && p->x.dangerousChildren == 0)
			mask[0] &= ~p->x.clobbersWhich;
		r = askreg(s, mask);
		if (r == NULL && saveMask != mask[0]) {
			mask[0] = saveMask;
			r = askreg(s,mask);
		}
		else if (saveMask != mask[0])
			mask[0] = saveMask;
	}

	if (r == NULL) {
		r = spillee(s, p);
		assert(r);
		spill(r->x.regnode->mask, r->x.regnode->set, p);
		putreg(r);
		r = askreg(s, mask);
		if (r == NULL) {
			if(OptimizeFlag) {
				if (IntermediateLanguageFile) {
					fprintf(ilFile,StrTab[244]);// <Fatal error:\n>
					ildumptree(p,0);
					r = spillee(s,p);
					fprintf(ilFile,"\nregister: %s\n",r->x.name);
				}
				fatal("getreg",StrTab[245],0);// <Expression too complicated\nEnclose this function within #pragma optimize(0)/(1)\n>
			}
			else fatal("getreg",StrTab[246],1);// <No more registers available>
		}
	}
	assert(r->x.regnode);
	r->x.regnode->vbl = NULL;
	return r;
}
int askregvar(Symbol p,Symbol regs)
{
	Symbol r;

	assert(p);
	if (p->sclass != REGISTER)
		return 0;
	else if (!isscalar(p->type)) {
		p->sclass = AUTO;
		return 0;
	}
	else if (p->temporary && p->u.t.cse) {
		p->x.name = "?";
		return 1;
	}
	/*
	test if SetupRegisterVariables has assigned this already...
	*/
	else if (p->x.regnode && OptimizeFlag)
		return 1;
	else if (p->x.switchSymbol &&
			p->generated) {
			Symbol r = intreg[0];
			p->sclass = REGISTER;
			p->x.regnode = r->x.regnode;
			p->x.regnode->vbl = p;
			p->x.name = r->x.name;
			return 1;
	}
	else if ((r = askreg(regs, vmask)) != NULL) {
		p->x.regnode = r->x.regnode;
		p->x.regnode->vbl = p;
		p->x.name = r->x.name;
#ifdef DODEBUG
		dumpregs("(allocating %s to symbol %s)\n", p->x.name, p->name,NULL);
#endif
		return 1;
	}
	else {
		p->sclass = AUTO;
		return 0;
	}
}
void linearize(Node p,Node next)
{
	int i;

	for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++)
		linearize(p->x.kids[i], next);
	relink(next->x.prev, p);
	relink(p, next);
#ifdef DODEBUG
	fprint(2, "(listing %x)\n", p);
#endif
}
static void ralloc(Node p)
{
	int i,tmpflag=0;
	int EdxWasInUse=0;
	unsigned mask[2];

	mask[0] = tmask[0];
	mask[1] = tmask[1];
	assert(p);
#ifdef DODEBUG
	fprint(2, "(rallocing %x: %s)\n", p,IR->x._opname[p->op]);
#endif
	for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
		Node kid = p->x.kids[i];
		Symbol r = kid->syms[RX];
		assert(r && kid->x.registered);
		if ((r->sclass != REGISTER || (r->temporary && r->generated)) &&
			r->x.lastuse == kid)
			putreg(r);
	}
	if (p->op == DIVI)
		EdxWasInUse = (~freemask[0]) & ((1 << 2)|1);
	if (!p->x.registered && (NeedsReg[opindex(p->op)] || p->op == JUMPI)
	&& rmap[optype(p->op)]) {
		Symbol sym = p->syms[RX], set = sym;
		assert(sym);
		if (sym->temporary && sym->u.t.cse) {
			tmpflag = 1;
			set = rmap[optype(p->op)];
		}
		assert(set);
		if (set->sclass != REGISTER) {
			Symbol r;
			char *prule = IR->x._templates[getrule(p, p->x.inst)];
			if (*prule == '?')
				for (i = 1; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
					Symbol r = p->x.kids[i]->syms[RX];
					assert(p->x.kids[i]->x.registered);
					assert(r && r->x.regnode);
//					assert(sym->x.wildcard || sym != r);
					if (!(sym->x.wildcard || sym != r )) {
						if (strcmp(r->x.name,sym->x.name)) {
#if 0
						dumpregs("error in %s %x %s\n",r->x.name,(char *)p,opname(p->op));
						dumptree(p,0);
						dumptree(p->x.kids[i],0);
#endif
						assert(0);
						}
					}

					mask[r->x.regnode->set] &= ~r->x.regnode->mask;
				}
			/* Avoid ESI and EDI when converting int to char, because
			those registers have no byte registers
			*/
			if ((p->x.next && ((optype(p->x.next->op) == C) )
					|| optype(p->op) == C)) {
				mask[0] &= ~((1 << 6)|(1<< 7));
			}
//			else if (generic(p->op) == LSH) {
				/* avoid ECX with shifts */
//				mask[0] &= ~(1 << 1);
//			}
			if (p->x.intrinsicArg) {
				r = AssignIntrinsicArg(p);
				if (r == NULL)
					r = getreg(set, mask, p, tmpflag);
			}
			else
				r = getreg(set, mask, p,tmpflag);
			if (sym->temporary && sym->u.t.cse) {
				Node q;
				r->x.lastuse = sym->x.lastuse;
				for (q = sym->x.lastuse; q; q = q->x.prevuse) {
					q->syms[RX] = r;
					q->x.registered = 1;
					if (q->x.copy)
						q->x.equatable = 1;
				}
			} else {
				p->syms[RX] = r;
				r->x.lastuse = p;
			}
#ifdef DODEBUG
			dumpregs("(allocating %s to node %x %s)\n", r->x.name, (char *) p,opname(p->op));
			dumptree(p,0);
#endif
		}
	}
	p->x.registered = 1;
	if (p->op != DIVI || EdxWasInUse)
		(*IR->x.clobber)(p);
}
static Symbol spillee(Symbol set,Node here)
{
	Symbol bestreg = NULL;
	int bestdist = -1, i;

	assert(set);
	if (!set->x.wildcard)
		return set;
	if (FunctionInfo.leafFunction == 0)
	for (i = 31; i >= 0; i--) {
		Symbol ri = set->x.wildcard[i];
		if (ri != NULL && ri->x.lastuse && ri->x.regnode->vbl == NULL
		&& ri->x.regnode->mask&tmask[ri->x.regnode->set] ) {
			Regnode rn = ri->x.regnode;
			Node q = here;
			int dist = 0;
			for (; q && !uses(q, rn->mask); q = q->x.next)
				dist++;
			if (q && dist > bestdist) {
				bestdist = dist;
				bestreg = ri;
			}
		}
	}
	else {
		for (i = 0; i < 32; i++) {
			Symbol ri = set->x.wildcard[i];
			if (ri != NULL && ri->x.lastuse && ri->x.regnode->vbl == NULL
			&& ri->x.regnode->mask&tmask[ri->x.regnode->set]) {
				Regnode rn = ri->x.regnode;
				Node q = here;
				int dist = 0;
				for (; q && !uses(q, rn->mask); q = q->x.next)
					dist++;
				if (q && dist > bestdist) {
					bestdist = dist;
					bestreg = ri;
				}
			}
		}
	}
	return bestreg;
}
static int uses(Node p,unsigned mask)
{
	int i;
	Node q;

	for (i = 0; i < NELEMS(p->x.kids)
		&& (q = p->x.kids[i]) != NULL; i++)
		if (q->x.registered
		&& mask&q->syms[RX]->x.regnode->mask)
			return 1;
	return 0;
}
static void spillr(Symbol r,Node here)
{
	int i;
	Node p = r->x.lastuse;
	Symbol tmp;

	if (p == NULL) {
		putreg(r);
		return;
	}
	assert(p);
	while (p->x.prevuse) {
		assert(r == p->syms[RX]);
		p = p->x.prevuse;
	}
	assert(p->x.registered && !readsreg(p));
	tmp = newtemp(AUTO, optype(p->op));
	genspill(r, p, tmp);
	for (p = here->x.next; p; p = p->x.next)
		for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
			Node k = p->x.kids[i];

			if (k->x.registered && k->syms[RX] == r)
				genreload(p, tmp, i);
		}
	putreg(r);
}
int NrOfSpills;
static void genspill(Symbol r,Node last,Symbol tmp)
{
	Node p, q;
	Symbol s;
	unsigned ty;

	if (IntermediateLanguageFile) {
		fprintf(ilFile, "(spilling %s to local %s)\n", r->x.name, tmp->x.name);
		fprintf(ilFile, "(genspill: ");
		ildumptree(last,0);
		fprintf(ilFile, ")\nFree regs: ");
		if (freemask[0] & 1) fprintf(ilFile," eax");
		if (freemask[0] & (1 << 1)) fprintf(ilFile," ecx");
		if (freemask[0] & (1 << 2)) fprintf(ilFile," edx");
		if (freemask[0] & (1 << 3)) fprintf(ilFile," ebx");
		if (freemask[0] & (1 << 6)) fprintf(ilFile," esi");
		if (freemask[0] & (1 << 7)) fprintf(ilFile," edi");
		fprintf(ilFile,"\n");
	}
	NrOfSpills++;
	ty = optype(last->op);
	if (ty == U)
		ty = I;
	NEW0(s, FUNC);
	s->sclass = REGISTER;
	s->x.name = r->x.name;
	s->x.regnode = r->x.regnode;
	s->x.regnode->vbl = s;
	q = newnode(ADDRLP, NULL, NULL, s);
	q = newnode(INDIR + ty, q, NULL, NULL);
	p = newnode(ADDRLP, NULL, NULL, tmp);
	p = newnode(ASGN + ty, p, q, NULL);
	p->x.spills = 1;
	rewrite(p);
	prune(p, &q);
	q = last->x.next;
	linearize(p, q);
	for (p = last->x.next; p != q; p = p->x.next) {
		ralloc(p);
		assert(!p->x.listed || !NeedsReg[opindex(p->op)] || !rmap[optype(p->op)]);
	}
}

static void genreload(Node p,Symbol tmp,int i)
{
	Node q;
	int ty;
#ifdef DODEBUG
	fprint(2, "(replacing %x with a reload from %s)\n", p->x.kids[i], tmp->x.name);
	fprint(2, "(genreload: ");
	dumptree(p->x.kids[i],0);
	fprint(2, ")\n");
#endif
	ty = optype(p->x.kids[i]->op);
	if (ty == U)
		ty = I;
	q = newnode(ADDRLP, NULL, NULL, tmp);
	p->x.kids[i] = newnode(INDIR + ty, q, NULL, NULL);
	rewrite(p->x.kids[i]);
	prune(p->x.kids[i], &q);
	reprune(&p->kids[1], reprune(&p->kids[0], 0, i, p), i, p);
	prune(p, &q);
	linearize(p->x.kids[i], p);
}
static int reprune(Node *pp,int k,int n,Node p)
{
	struct node x, *q = *pp;

	if (q == NULL || k > n)
		return k;
	else if (q->x.inst == 0)
		return reprune(&q->kids[1],
			reprune(&q->kids[0], k, n, p), n, p);
	else if (k == n) {
#ifdef DODEBUG
		fprint(2, "(reprune changes %x from %x to %x)\n", pp, *pp, p->x.kids[n]);
#endif
		*pp = p->x.kids[n];
		x = *p;		/* explain this */
		(IR->x.target)(&x);
	}
	return k + 1;
}
void spill(unsigned mask,int n,Node here)
{
	int i;
	Node p;

	here->x.spills = 1;
	usedmask[n] |= mask;
	if (mask&~freemask[n])
		for (p = here; p; p = p->x.next)
			for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
				Symbol r = p->x.kids[i]->syms[RX];
				assert(r);
				if (p->x.kids[i]->x.registered && r->x.regnode->set == n
				&& r->x.regnode->mask&mask)
					spillr(r, here);
			}
}
#ifdef DODEBUG

static void dumpregs(char *msg,char *a,char *b,char *c)
{
	fprint(2, msg, a, b, c);
	fprint(2, "(free[0]=%x)", freemask[0]);
	if (freemask[0] & 1) fprint(2," eax");
	if (freemask[0] & (1 << 1)) fprint(2," ecx");
	if (freemask[0] & (1 << 2)) fprint(2," edx");
	if (freemask[0] & (1 << 3)) fprint(2," ebx");
	if (freemask[0] & (1 << 6)) fprint(2," esi");
	if (freemask[0] & (1 << 7)) fprint(2," edi");
	fprint(2,"\n");
}
#endif
int getregnum(Node p)
{
	assert(p && p->syms[RX] && p->syms[RX]->x.regnode);
	return p->syms[RX]->x.regnode->number;
}


unsigned regloc(Symbol p)
{
	assert(p && p->sclass == REGISTER && p->sclass == REGISTER && p->x.regnode);
	return p->x.regnode->set<<8 | p->x.regnode->number;
}

⌨️ 快捷键说明

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