forsyth20121205-174063a80cc13 years agoHistory
764 lines · 13.4 KB · C
RawDownload
#include	"l.h" voiddodata(void){	int i;	Sym *s;	Prog *p;	long t, u; 	if(debug['v'])		Bprint(&bso, "%5.2f dodata\n", cputime());	Bflush(&bso);	for(p = datap; p != P; p = p->link) {		s = p->from.sym;		if(p->as == ADYNT || p->as == AINIT)			s->value = dtype;		if(s->type == SBSS)			s->type = SDATA;		if(s->type != SDATA)			diag("initialize non-data (%d): %s\n%P",				s->type, s->name, p);		t = p->from.offset + p->width;		if(t > s->value)			diag("initialize bounds (%ld): %s\n%P",				s->value, s->name, p);	}	/* allocate small guys */	datsize = 0;	for(i=0; i<NHASH; i++)	for(s = hash[i]; s != S; s = s->link) {		if(s->type != SDATA)		if(s->type != SBSS)			continue;		t = s->value;		if(t == 0) {			diag("%s: no size", s->name);			t = 1;		}		t = rnd(t, 4);;		s->value = t;		if(t > MINSIZ)			continue;		s->value = datsize;		datsize += t;		s->type = SDATA1;	} 	/* allocate the rest of the data */	for(i=0; i<NHASH; i++)	for(s = hash[i]; s != S; s = s->link) {		if(s->type != SDATA) {			if(s->type == SDATA1)				s->type = SDATA;			continue;		}		t = s->value;		s->value = datsize;		datsize += t;	} 	if(debug['j']) {		/*		 * pad data with bss that fits up to next		 * 8k boundary, then push data to 8k		 */		u = rnd(datsize, 8192);		u -= datsize;		for(i=0; i<NHASH; i++)		for(s = hash[i]; s != S; s = s->link) {			if(s->type != SBSS)				continue;			t = s->value;			if(t > u)				continue;			u -= t;			s->value = datsize;			s->type = SDATA;			datsize += t;		}		datsize += u;	} 	/* now the bss */	bsssize = 0;	for(i=0; i<NHASH; i++)	for(s = hash[i]; s != S; s = s->link) {		if(s->type != SBSS)			continue;		t = s->value;		s->value = bsssize + datsize;		bsssize += t;	}	xdefine("edata", SBSS, datsize);	xdefine("end", SBSS, bsssize + datsize);} Prog*brchain(Prog *p){	int i; 	for(i=0; i<20; i++) {		if(p == P || p->as != AJMP)			return p;		p = p->pcond;	}	return P;} voidfollow(void){ 	if(debug['v'])		Bprint(&bso, "%5.2f follow\n", cputime());	Bflush(&bso);	firstp = prg();	lastp = firstp;	xfol(textp);	lastp->link = P;	firstp = firstp->link;} voidxfol(Prog *p){	Prog *q;	int i;	enum as a; loop:	if(p == P)		return;	if(p->as == ATEXT)		curtext = p;	if(p->as == AJMP)	if((q = p->pcond) != P) {		p->mark = 1;		p = q;		if(p->mark == 0)			goto loop;	}	if(p->mark) {		/* copy up to 4 instructions to avoid branch */		for(i=0,q=p; i<4; i++,q=q->link) {			if(q == P)				break;			if(q == lastp)				break;			a = q->as;			if(a == ANOP) {				i--;				continue;			}			switch(a) {			case AJMP:			case ARET:			case AIRETL: 			case APUSHL:			case APUSHFL:			case APUSHW:			case APUSHFW:			case APOPL:			case APOPFL:			case APOPW:			case APOPFW:				goto brk;			}			if(q->pcond == P || q->pcond->mark)				continue;			if(a == ACALL || a == ALOOP)				continue;			for(;;) {				if(p->as == ANOP) {					p = p->link;					continue;				}				q = copyp(p);				p = p->link;				q->mark = 1;				lastp->link = q;				lastp = q;				if(q->as != a || q->pcond == P || q->pcond->mark)					continue; 				q->as = relinv(q->as);				p = q->pcond;				q->pcond = q->link;				q->link = p;				xfol(q->link);				p = q->link;				if(p->mark)					return;				goto loop;			}		} /* */	brk:;		q = prg();		q->as = AJMP;		q->line = p->line;		q->to.type = D_BRANCH;		q->to.offset = p->pc;		q->pcond = p;		p = q;	}	p->mark = 1;	lastp->link = p;	lastp = p;	a = p->as;	if(a == AJMP || a == ARET || a == AIRETL)		return;	if(p->pcond != P)	if(a != ACALL) {		q = brchain(p->link);		if(q != P && q->mark)		if(a != ALOOP) {			p->as = relinv(a);			p->link = p->pcond;			p->pcond = q;		}		xfol(p->link);		q = brchain(p->pcond);		if(q->mark) {			p->pcond = q;			return;		}		p = q;		goto loop;	}	p = p->link;	goto loop;} intrelinv(int a){ 	switch(a) {	case AJEQ:	return AJNE;	case AJNE:	return AJEQ;	case AJLE:	return AJGT;	case AJLS:	return AJHI;	case AJLT:	return AJGE;	case AJMI:	return AJPL;	case AJGE:	return AJLT;	case AJPL:	return AJMI;	case AJGT:	return AJLE;	case AJHI:	return AJLS;	case AJCS:	return AJCC;	case AJCC:	return AJCS;	case AJPS:	return AJPC;	case AJPC:	return AJPS;	case AJOS:	return AJOC;	case AJOC:	return AJOS;	}	diag("unknown relation: %s in %s", anames[a], TNAME);	return a;} voiddoinit(void){	Sym *s;	Prog *p;	int x; 	for(p = datap; p != P; p = p->link) {		x = p->to.type;		if(x != D_EXTERN && x != D_STATIC)			continue;		s = p->to.sym;		if(s->type == 0 || s->type == SXREF)			diag("undefined %s initializer of %s",				s->name, p->from.sym->name);		p->to.offset += s->value;		p->to.type = D_CONST;		if(s->type == SDATA || s->type == SBSS)			p->to.offset += INITDAT;	}} voidpatch(void){	long c;	Prog *p, *q;	Sym *s;	long vexit; 	if(debug['v'])		Bprint(&bso, "%5.2f mkfwd\n", cputime());	Bflush(&bso);	mkfwd();	if(debug['v'])		Bprint(&bso, "%5.2f patch\n", cputime());	Bflush(&bso);	s = lookup("exit", 0);	vexit = s->value;	for(p = firstp; p != P; p = p->link) {		if(p->as == ATEXT)			curtext = p;		if(p->as == ACALL || p->as == ARET) {			s = p->to.sym;			if(s) {				if(debug['c'])					Bprint(&bso, "%s calls %s\n", TNAME, s->name);				switch(s->type) {				default:					diag("undefined: %s in %s", s->name, TNAME);					s->type = STEXT;					s->value = vexit;					break;	/* or fall through to set offset? */				case STEXT:					p->to.offset = s->value;					break;				case SUNDEF:					p->pcond = UP;					p->to.offset = 0;					break;				}				p->to.type = D_BRANCH;			}		}		if(p->to.type != D_BRANCH || p->pcond == UP)			continue;		c = p->to.offset;		for(q = firstp; q != P;) {			if(q->forwd != P)			if(c >= q->forwd->pc) {				q = q->forwd;				continue;			}			if(c == q->pc)				break;			q = q->link;		}		if(q == P) {			diag("branch out of range in %s\n%P", TNAME, p);			p->to.type = D_NONE;		}		p->pcond = q;	} 	for(p = firstp; p != P; p = p->link) {		if(p->as == ATEXT)			curtext = p;		p->mark = 0;	/* initialization for follow */		if(p->pcond != P && p->pcond != UP) {			p->pcond = brloop(p->pcond);			if(p->pcond != P)			if(p->to.type == D_BRANCH)				p->to.offset = p->pcond->pc;		}	}} #define	LOG	5voidmkfwd(void){	Prog *p;	int i;	long dwn[LOG], cnt[LOG];	Prog *lst[LOG]; 	for(i=0; i<LOG; i++) {		if(i == 0)			cnt[i] = 1; else			cnt[i] = LOG * cnt[i-1];		dwn[i] = 1;		lst[i] = P;	}	i = 0;	for(p = firstp; p != P; p = p->link) {		if(p->as == ATEXT)			curtext = p;		i--;		if(i < 0)			i = LOG-1;		p->forwd = P;		dwn[i]--;		if(dwn[i] <= 0) {			dwn[i] = cnt[i];			if(lst[i] != P)				lst[i]->forwd = p;			lst[i] = p;		}	}} Prog*brloop(Prog *p){	int c;	Prog *q; 	c = 0;	for(q = p; q != P; q = q->pcond) {		if(q->as != AJMP)			break;		c++;		if(c >= 5000)			return P;	}	return q;} voiddostkoff(void){	Prog *p, *q;	long autoffset, deltasp;	int a, f, curframe, curbecome, maxbecome; 	curframe = 0;	curbecome = 0;	maxbecome = 0;	curtext = 0;	for(p = firstp; p != P; p = p->link) { 		/* find out how much arg space is used in this TEXT */		if(p->to.type == (D_INDIR+D_SP))			if(p->to.offset > curframe)				curframe = p->to.offset; 		switch(p->as) {		case ATEXT:			if(curtext && curtext->from.sym) {				curtext->from.sym->frame = curframe;				curtext->from.sym->become = curbecome;				if(curbecome > maxbecome)					maxbecome = curbecome;			}			curframe = 0;			curbecome = 0; 			curtext = p;			break; 		case ARET:			/* special form of RET is BECOME */			if(p->from.type == D_CONST)				if(p->from.offset > curbecome)					curbecome = p->from.offset;			break;		}	}	if(curtext && curtext->from.sym) {		curtext->from.sym->frame = curframe;		curtext->from.sym->become = curbecome;		if(curbecome > maxbecome)			maxbecome = curbecome;	} 	if(debug['b'])		print("max become = %d\n", maxbecome);	xdefine("ALEFbecome", STEXT, maxbecome); 	curtext = 0;	for(p = firstp; p != P; p = p->link) {		switch(p->as) {		case ATEXT:			curtext = p;			break;		case ACALL:			if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) {				f = maxbecome - curtext->from.sym->frame;				if(f <= 0)					break;				/* calling a become or calling a variable */				if(p->to.sym == S || p->to.sym->become) {					curtext->to.offset += f;					if(debug['b']) {						curp = p;						print("%D calling %D increase %d\n",							&curtext->from, &p->to, f);					}				}			}			break;		}	} 	autoffset = 0;	deltasp = 0;	for(p = firstp; p != P; p = p->link) {		if(p->as == ATEXT) {			curtext = p;			autoffset = p->to.offset;			if(autoffset < 0)				autoffset = 0;			if(autoffset) {				p = appendp(p);				p->as = AADJSP;				p->from.type = D_CONST;				p->from.offset = autoffset;			}			deltasp = autoffset;

Lines 1–500 of 764.