Charles.Forsyth20061220965a0ca19 years agoHistory
1270 lines · 19.1 KB · C
RawDownload
#include "gc.h" voidginit(void){	int i;	Type *t; 	thechar = 'k';	thestring = "sparc";	exregoffset = REGEXT;	exfregoffset = FREGEXT;	listinit();	nstring = 0;	mnstring = 0;	nrathole = 0;	pc = 0;	breakpc = -1;	continpc = -1;	cases = C;	firstp = P;	lastp = P;	tfield = types[TLONG]; 	zprog.link = P;	zprog.as = AGOK;	zprog.reg = NREG;	zprog.from.type = D_NONE;	zprog.from.name = D_NONE;	zprog.from.reg = NREG;	zprog.to = zprog.from; 	regnode.op = OREGISTER;	regnode.class = CEXREG;	regnode.reg = 0;	regnode.complex = 0;	regnode.addable = 11;	regnode.type = types[TLONG]; 	constnode.op = OCONST;	constnode.class = CXXX;	constnode.complex = 0;	constnode.addable = 20;	constnode.type = types[TLONG]; 	fconstnode.op = OCONST;	fconstnode.class = CXXX;	fconstnode.complex = 0;	fconstnode.addable = 20;	fconstnode.type = types[TDOUBLE]; 	nodsafe = new(ONAME, Z, Z);	nodsafe->sym = slookup(".safe");	nodsafe->type = types[TINT];	nodsafe->etype = types[TINT]->etype;	nodsafe->class = CAUTO;	complex(nodsafe); 	t = typ(TARRAY, types[TCHAR]);	symrathole = slookup(".rathole");	symrathole->class = CGLOBL;	symrathole->type = t; 	nodrat = new(ONAME, Z, Z);	nodrat->sym = symrathole;	nodrat->type = types[TIND];	nodrat->etype = TVOID;	nodrat->class = CGLOBL;	complex(nodrat);	nodrat->type = t; 	nodret = new(ONAME, Z, Z);	nodret->sym = slookup(".ret");	nodret->type = types[TIND];	nodret->etype = TIND;	nodret->class = CPARAM;	nodret = new(OIND, nodret, Z);	complex(nodret); 	com64init(); 	memset(reg, 0, sizeof(reg));	reg[REGZERO] = 1;	reg[REGLINK] = 1;	reg[REGTMP] = 1;	for(i=NREG; i<NREG+NREG; i+=2)		reg[i+1] = 1;} voidgclean(void){	int i;	Sym *s; 	for(i=0; i<NREG; i++)		if(i != REGZERO && i != REGTMP && i != REGLINK)		if(reg[i])			diag(Z, "reg %d left allocated", i);	for(i=NREG; i<NREG+NREG; i+=2)		if(reg[i])			diag(Z, "freg %d left allocated", i-NREG);	while(mnstring)		outstring("", 1L);	symstring->type->width = nstring;	symrathole->type->width = nrathole;	for(i=0; i<NHASH; i++)	for(s = hash[i]; s != S; s = s->link) {		if(s->type == T)			continue;		if(s->type->width == 0)			continue;		if(s->class != CGLOBL && s->class != CSTATIC)			continue;		if(s->type == types[TENUM])			continue;		gpseudo(AGLOBL, s, nodconst(s->type->width));	}	nextpc();	p->as = AEND;	outcode();} voidnextpc(void){ 	p = alloc(sizeof(*p));	*p = zprog;	p->lineno = nearln;	pc++;	if(firstp == P) {		firstp = p;		lastp = p;		return;	}	lastp->link = p;	lastp = p;} voidgargs(Node *n, Node *tn1, Node *tn2){	long regs;	Node fnxargs[20], *fnxp; 	regs = cursafe; 	fnxp = fnxargs;	garg1(n, tn1, tn2, 0, &fnxp);	/* compile fns to temps */ 	curarg = 0;	fnxp = fnxargs;	garg1(n, tn1, tn2, 1, &fnxp);	/* compile normal args and temps */ 	cursafe = regs;} voidgarg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp){	Node nod; 	if(n == Z)		return;	if(n->op == OLIST) {		garg1(n->left, tn1, tn2, f, fnxp);		garg1(n->right, tn1, tn2, f, fnxp);		return;	}	if(f == 0) {		if(n->complex >= FNX) {			regsalloc(*fnxp, n);			nod = znode;			nod.op = OAS;			nod.left = *fnxp;			nod.right = n;			nod.type = n->type;			cgen(&nod, Z);			(*fnxp)++;		}		return;	}	if(typesuv[n->type->etype]) {		regaalloc(tn2, n);		if(n->complex >= FNX) {			sugen(*fnxp, tn2, n->type->width);			(*fnxp)++;		} else			sugen(n, tn2, n->type->width);		return;	}	if(REGARG && curarg == 0 && typechlp[n->type->etype]) {		regaalloc1(tn1, n);		if(n->complex >= FNX) {			cgen(*fnxp, tn1);			(*fnxp)++;		} else			cgen(n, tn1);		return;	}	if(vconst(n) == 0) {		regaalloc(tn2, n);		gopcode(OAS, n, Z, tn2);		return;	}	regalloc(tn1, n, Z);	if(n->complex >= FNX) {		cgen(*fnxp, tn1);		(*fnxp)++;	} else		cgen(n, tn1);	regaalloc(tn2, n);	gopcode(OAS, tn1, Z, tn2);	regfree(tn1);} Node*nod32const(vlong v){	constnode.vconst = v & MASK(32);	return &constnode;} Node*nodconst(long v){	constnode.vconst = v;	return &constnode;} Node*nodfconst(double d){	fconstnode.fconst = d;	return &fconstnode;} voidnodreg(Node *n, Node *nn, int reg){	*n = regnode;	n->reg = reg;	n->type = nn->type;	n->lineno = nn->lineno;} voidregret(Node *n, Node *nn){	int r; 	r = REGRET;	if(typefd[nn->type->etype])		r = FREGRET+NREG;	nodreg(n, nn, r);	reg[r]++;} voidregalloc(Node *n, Node *tn, Node *o){	int i, j;	static int lasti; 	switch(tn->type->etype) {	case TCHAR:	case TUCHAR:	case TSHORT:	case TUSHORT:	case TINT:	case TUINT:	case TLONG:	case TULONG:	case TIND:		if(o != Z && o->op == OREGISTER) {			i = o->reg;			if(i > 0 && i < NREG)				goto out;		}		j = lasti + REGRET+1;		for(i=REGRET+1; i<NREG; i++) {			if(j >= NREG)				j = REGRET+1;			if(reg[j] == 0) {				i = j;				goto out;			}			j++;		}		diag(tn, "out of fixed registers");		goto err; 	case TFLOAT:	case TDOUBLE:	case TVLONG:		if(o != Z && o->op == OREGISTER) {			i = o->reg;			if(i >= NREG && i < NREG+NREG)				goto out;		}		j = lasti*2 + NREG;		for(i=NREG; i<NREG+NREG; i+=2) {			if(j >= NREG+NREG)				j = NREG;			if(reg[j] == 0) {				i = j;				goto out;			}			j += 2;		}		diag(tn, "out of float registers");		goto err;	}	diag(tn, "unknown type in regalloc: %T", tn->type);err:	i = 0;out:	if(i)		reg[i]++;	lasti++;	if(lasti >= 5)		lasti = 0;	nodreg(n, tn, i);} voidregialloc(Node *n, Node *tn, Node *o){	Node nod; 	nod = *tn;	nod.type = types[TIND];	regalloc(n, &nod, o);} voidregfree(Node *n){	int i; 	i = 0;	if(n->op != OREGISTER && n->op != OINDREG)		goto err;	i = n->reg;	if(i < 0 || i >= sizeof(reg))		goto err;	if(reg[i] <= 0)		goto err;	reg[i]--;	return;err:	diag(n, "error in regfree: %d", i);} voidregsalloc(Node *n, Node *nn){	cursafe = align(cursafe, nn->type, Aaut3);	maxargsafe = maxround(maxargsafe, cursafe+curarg);	*n = *nodsafe;	n->xoffset = -(stkoff + cursafe);	n->type = nn->type;	n->etype = nn->type->etype;	n->lineno = nn->lineno;} voidregaalloc1(Node *n, Node *nn){	nodreg(n, nn, REGARG);	reg[REGARG]++;	curarg = align(curarg, nn->type, Aarg1);	curarg = align(curarg, nn->type, Aarg2);	maxargsafe = maxround(maxargsafe, cursafe+curarg);} voidregaalloc(Node *n, Node *nn){	curarg = align(curarg, nn->type, Aarg1);	*n = *nn;	n->op = OINDREG;	n->reg = REGSP;	n->xoffset = curarg + SZ_LONG;	n->complex = 0;	n->addable = 20;	curarg = align(curarg, nn->type, Aarg2);	maxargsafe = maxround(maxargsafe, cursafe+curarg);} voidregind(Node *n, Node *nn){ 	if(n->op != OREGISTER) {		diag(n, "regind not OREGISTER");		return;	}	n->op = OINDREG;	n->type = nn->type;} voidraddr(Node *n, Prog *p){	Adr a; 	naddr(n, &a);	if(a.type == D_CONST && a.offset == 0) {		a.type = D_REG;		a.reg = 0;	}	if(a.type != D_REG && a.type != D_FREG) {		if(n)			diag(n, "bad in raddr: %O", n->op);		else			diag(n, "bad in raddr: <null>");		p->reg = NREG;	} else		p->reg = a.reg;} voidnaddr(Node *n, Adr *a){	long v; 	a->type = D_NONE;	if(n == Z)		return;	switch(n->op) {	default:	bad:		diag(n, "bad in naddr: %O", n->op);		break; 	case OREGISTER:		a->type = D_REG;		a->sym = S;		a->reg = n->reg;		if(a->reg >= NREG) {			a->type = D_FREG;			a->reg -= NREG;		}		break; 	case OIND:		naddr(n->left, a);		if(a->type == D_REG) {			a->type = D_OREG;			break;		}		if(a->type == D_CONST) {			a->type = D_OREG;			break;		}		goto bad; 	case OINDREG:		a->type = D_OREG;		a->sym = S;		a->offset = n->xoffset;		a->reg = n->reg;		break; 	case ONAME:		a->etype = n->etype;		a->type = D_OREG;		a->name = D_STATIC;		a->sym = n->sym;		a->offset = n->xoffset;		if(n->class == CSTATIC)			break;		if(n->class == CEXTERN || n->class == CGLOBL) {			a->name = D_EXTERN;			break;		}		if(n->class == CAUTO) {			a->name = D_AUTO;			break;		}		if(n->class == CPARAM) {			a->name = D_PARAM;			break;		}		goto bad; 	case OCONST:		a->sym = S;		a->reg = NREG;		if(typefd[n->type->etype]) {			a->type = D_FCONST;			a->dval = n->fconst;		} else {			a->type = D_CONST;			a->offset = n->vconst;		}		break; 

Lines 1–500 of 1270.