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

📄 reg.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "gc.h"void	addsplits(void);Reg*rega(void){	Reg *r;	r = freer;	if(r == R) {		r = alloc(sizeof(*r));	} else		freer = r->link;	*r = zreg;	return r;}intrcmp(const void *a1, const void *a2){	Rgn *p1, *p2;	int c1, c2;	p1 = (Rgn*)a1;	p2 = (Rgn*)a2;	c1 = p2->cost;	c2 = p1->cost;	if(c1 -= c2)		return c1;	return p2->varno - p1->varno;}voidregopt(Prog *p){	Reg *r, *r1, *r2;	Prog *p1;	int i, z;	long initpc, val, npc;	ulong vreg;	Bits bit;	struct	{		long	m;		long	c;		Reg*	p;	} log5[6], *lp;	firstr = R;	lastr = R;	nvar = 0;	regbits = 0;	for(z=0; z<BITS; z++) {		externs.b[z] = 0;		params.b[z] = 0;		consts.b[z] = 0;		addrs.b[z] = 0;	}	/*	 * pass 1	 * build aux data structure	 * allocate pcs	 * find use and set of variables	 */	val = 5L * 5L * 5L * 5L * 5L;	lp = log5;	for(i=0; i<5; i++) {		lp->m = val;		lp->c = 0;		lp->p = R;		val /= 5L;		lp++;	}	val = 0;	for(; p != P; p = p->link) {		switch(p->as) {		case ADATA:		case AGLOBL:		case ANAME:		case ASIGNAME:			continue;		}		r = rega();		if(firstr == R) {			firstr = r;			lastr = r;		} else {			lastr->link = r;			r->p1 = lastr;			lastr->s1 = r;			lastr = r;		}		r->prog = p;		r->pc = val;		val++;		lp = log5;		for(i=0; i<5; i++) {			lp->c--;			if(lp->c <= 0) {				lp->c = lp->m;				if(lp->p != R)					lp->p->log5 = r;				lp->p = r;				(lp+1)->c = 0;				break;			}			lp++;		}		r1 = r->p1;		if(r1 != R)		switch(r1->prog->as) {		case ARET:		case AB:		case ARFE:			r->p1 = R;			r1->s1 = R;		}		/*		 * left side always read		 */		bit = mkvar(&p->from, p->as==AMOVW);		for(z=0; z<BITS; z++)			r->use1.b[z] |= bit.b[z];		/*		 * right side depends on opcode		 */		bit = mkvar(&p->to, 0);		if(bany(&bit))		switch(p->as) {		default:			diag(Z, "reg: unknown asop: %A", p->as);			break;		/*		 * right side write		 */		case ANOP:		case AMOVB:		case AMOVBU:		case AMOVH:		case AMOVHU:		case AMOVW:		case AMOVF:		case AMOVD:			for(z=0; z<BITS; z++)				r->set.b[z] |= bit.b[z];			break;		/*		 * funny		 */		case ABL:			for(z=0; z<BITS; z++)				addrs.b[z] |= bit.b[z];			break;		}		if(p->as == AMOVM) {			if(p->from.type == D_CONST)				z = p->from.offset;			else				z = p->to.offset;			for(i=0; z; i++) {				if(z&1)					regbits |= RtoB(i);				z >>= 1;			}		}	}	if(firstr == R)		return;	initpc = pc - val;	npc = val;	/*	 * pass 2	 * turn branch references to pointers	 * build back pointers	 */	for(r = firstr; r != R; r = r->link) {		p = r->prog;		if(p->to.type == D_BRANCH) {			val = p->to.offset - initpc;			r1 = firstr;			while(r1 != R) {				r2 = r1->log5;				if(r2 != R && val >= r2->pc) {					r1 = r2;					continue;				}				if(r1->pc == val)					break;				r1 = r1->link;			}			if(r1 == R) {				nearln = p->lineno;				diag(Z, "ref not found\n%P", p);				continue;			}			if(r1 == r) {				nearln = p->lineno;				diag(Z, "ref to self\n%P", p);				continue;			}			r->s2 = r1;			r->p2link = r1->p2;			r1->p2 = r;		}	}	if(debug['R']) {		p = firstr->prog;		print("\n%L %D\n", p->lineno, &p->from);	}	/*	 * pass 2.5	 * find looping structure	 */	for(r = firstr; r != R; r = r->link)		r->active = 0;	change = 0;	loopit(firstr, npc);	/*	 * pass 3	 * iterate propagating usage	 * 	back until flow graph is complete	 */loop1:	change = 0;	for(r = firstr; r != R; r = r->link)		r->active = 0;	for(r = firstr; r != R; r = r->link)		if(r->prog->as == ARET)			prop(r, zbits, zbits);loop11:	/* pick up unreachable code */	i = 0;	for(r = firstr; r != R; r = r1) {		r1 = r->link;		if(r1 && r1->active && !r->active) {			prop(r, zbits, zbits);			i = 1;		}	}	if(i)		goto loop11;	if(change)		goto loop1;	/*	 * pass 4	 * iterate propagating register/variable synchrony	 * 	forward until graph is complete	 */loop2:	change = 0;	for(r = firstr; r != R; r = r->link)		r->active = 0;	synch(firstr, zbits);	if(change)		goto loop2;	addsplits();	if(debug['R'] && debug['v']) {		print("\nprop structure:\n");		for(r = firstr; r != R; r = r->link) {			print("%ld:%P", r->loop, r->prog);			for(z=0; z<BITS; z++)				bit.b[z] = r->set.b[z] |					r->refahead.b[z] | r->calahead.b[z] |					r->refbehind.b[z] | r->calbehind.b[z] |					r->use1.b[z] | r->use2.b[z];			if(bany(&bit)) {				print("\t");				if(bany(&r->use1))					print(" u1=%B", r->use1);				if(bany(&r->use2))					print(" u2=%B", r->use2);				if(bany(&r->set))					print(" st=%B", r->set);				if(bany(&r->refahead))					print(" ra=%B", r->refahead);				if(bany(&r->calahead))					print(" ca=%B", r->calahead);				if(bany(&r->refbehind))					print(" rb=%B", r->refbehind);				if(bany(&r->calbehind))					print(" cb=%B", r->calbehind);			}			print("\n");		}	}	/*	 * pass 5	 * isolate regions	 * calculate costs (paint1)	 */	r = firstr;	if(r) {		for(z=0; z<BITS; z++)			bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &			  ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);		if(bany(&bit)) {			nearln = r->prog->lineno;			warn(Z, "used and not set: %B", bit);			if(debug['R'] && !debug['w'])				print("used and not set: %B\n", bit);		}	}	for(r = firstr; r != R; r = r->link)		r->act = zbits;	rgp = region;	nregion = 0;	for(r = firstr; r != R; r = r->link) {		for(z=0; z<BITS; z++)			bit.b[z] = r->set.b[z] &			  ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]);		if(bany(&bit)) {			nearln = r->prog->lineno;			warn(Z, "set and not used: %B", bit);			if(debug['R'])				print("set and not used: %B\n", bit);			excise(r);		}		for(z=0; z<BITS; z++)			bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]);		while(bany(&bit)) {			i = bnum(bit);			rgp->enter = r;			rgp->varno = i;			change = 0;			if(debug['R'] && debug['v'])				print("\n");			paint1(r, i);			bit.b[i/32] &= ~(1L<<(i%32));			if(change <= 0) {				if(debug['R'])					print("%L $%d: %B\n",						r->prog->lineno, change, blsh(i));				continue;			}			rgp->cost = change;			nregion++;			if(nregion >= NRGN) {				warn(Z, "too many regions");				goto brk;			}			rgp++;		}	}brk:	qsort(region, nregion, sizeof(region[0]), rcmp);	/*	 * pass 6	 * determine used registers (paint2)	 * replace code (paint3)	 */	rgp = region;	for(i=0; i<nregion; i++) {		bit = blsh(rgp->varno);		vreg = paint2(rgp->enter, rgp->varno);		vreg = allreg(vreg, rgp);		if(debug['R']) {			if(rgp->regno >= NREG)				print("%L $%d F%d: %B\n",					rgp->enter->prog->lineno,					rgp->cost,					rgp->regno-NREG,					bit);			else				print("%L $%d R%d: %B\n",					rgp->enter->prog->lineno,					rgp->cost,					rgp->regno,					bit);		}		if(rgp->regno != 0)			paint3(rgp->enter, rgp->varno, vreg, rgp->regno);		rgp++;	}	/*	 * pass 7	 * peep-hole on basic block	 */	if(!debug['R'] || debug['P'])		peep();	/*	 * pass 8	 * recalculate pc	 */	val = initpc;	for(r = firstr; r != R; r = r1) {		r->pc = val;		p = r->prog;		p1 = P;		r1 = r->link;		if(r1 != R)			p1 = r1->prog;		for(; p != p1; p = p->link) {			switch(p->as) {			default:				val++;				break;			case ANOP:			case ADATA:			case AGLOBL:			case ANAME:			case ASIGNAME:				break;			}		}	}	pc = val;	/*	 * fix up branches	 */	if(debug['R'])		if(bany(&addrs))			print("addrs: %B\n", addrs);	r1 = 0; /* set */	for(r = firstr; r != R; r = r->link) {		p = r->prog;		if(p->to.type == D_BRANCH)			p->to.offset = r->s2->pc;		r1 = r;	}	/*	 * last pass	 * eliminate nops	 * free aux structures	 */	for(p = firstr->prog; p != P; p = p->link){		while(p->link && p->link->as == ANOP)			p->link = p->link->link;	}	if(r1 != R) {		r1->link = freer;		freer = firstr;	}}voidaddsplits(void){	Reg *r, *r1;	int z, i;	Bits bit;	for(r = firstr; r != R; r = r->link) {		if(r->loop > 1)			continue;		if(r->prog->as == ABL)			continue;		for(r1 = r->p2; r1 != R; r1 = r1->p2link) {			if(r1->loop <= 1)				continue;			for(z=0; z<BITS; z++)				bit.b[z] = r1->calbehind.b[z] &					(r->refahead.b[z] | r->use1.b[z] | r->use2.b[z]) &					~(r->calahead.b[z] & addrs.b[z]);			while(bany(&bit)) {				i = bnum(bit);				bit.b[i/32] &= ~(1L << (i%32));			}		}	}}/* * add mov b,rn * just after r */voidaddmove(Reg *r, int bn, int rn, int f){	Prog *p, *p1;	Adr *a;	Var *v;	p1 = alloc(sizeof(*p1));	*p1 = zprog;	p = r->prog;	p1->link = p->link;	p->link = p1;	p1->lineno = p->lineno;	v = var + bn;	a = &p1->to;	a->sym = v->sym;	a->name = v->name;	a->offset = v->offset;	a->etype = v->etype;	a->type = D_OREG;	if(a->etype == TARRAY || a->sym == S)		a->type = D_CONST;	p1->as = AMOVW;	if(v->etype == TCHAR || v->etype == TUCHAR)		p1->as = AMOVB;	if(v->etype == TSHORT || v->etype == TUSHORT)		p1->as = AMOVH;	if(v->etype == TFLOAT)		p1->as = AMOVF;	if(v->etype == TDOUBLE)		p1->as = AMOVD;	p1->from.type = D_REG;	p1->from.reg = rn;	if(rn >= NREG) {		p1->from.type = D_FREG;		p1->from.reg = rn-NREG;	}	if(!f) {		p1->from = *a;		*a = zprog.from;		a->type = D_REG;		a->reg = rn;		if(rn >= NREG) {			a->type = D_FREG;			a->reg = rn-NREG;		}		if(v->etype == TUCHAR)			p1->as = AMOVBU;		if(v->etype == TUSHORT)			p1->as = AMOVHU;	}	if(debug['R'])		print("%P\t.a%P\n", p, p1);}Bitsmkvar(Adr *a, int docon){	Var *v;	int i, t, n, et, z;	long o;	Bits bit;	Sym *s;	t = a->type;	if(t == D_REG && a->reg != NREG)		regbits |= RtoB(a->reg);	if(t == D_FREG && a->reg != NREG)		regbits |= FtoB(a->reg);	s = a->sym;	o = a->offset;	et = a->etype;	if(s == S) {		if(t != D_CONST || !docon || a->reg != NREG)			goto none;		et = TLONG;	}	if(t == D_CONST) {		if(s == S && sval(o))			goto none;	}	n = a->name;	v = var;	for(i=0; i<nvar; i++) {

⌨️ 快捷键说明

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