forsyth20121205-174063a80cc13 years agoHistory
1514 lines · 26.5 KB · C
RawDownload
#include "gc.h" voidginit(void){	int i;	Type *t; 	thechar = '6';	thestring = "amd64";	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[TINT]; 	typeword = typechlvp;	typecmplx = typesu; 	/* TO DO */	memmove(typechlpv, typechlp, sizeof(typechlpv));	typechlpv[TVLONG] = 1;	typechlpv[TUVLONG] = 1; 	zprog.link = P;	zprog.as = AGOK;	zprog.from.type = D_NONE;	zprog.from.index = D_NONE;	zprog.from.scale = 0;	zprog.to = zprog.from; 	lregnode.op = OREGISTER;	lregnode.class = CEXREG;	lregnode.reg = REGTMP;	lregnode.complex = 0;	lregnode.addable = 11;	lregnode.type = types[TLONG]; 	qregnode = lregnode;	qregnode.type = types[TVLONG]; 	constnode.op = OCONST;	constnode.class = CXXX;	constnode.complex = 0;	constnode.addable = 20;	constnode.type = types[TLONG]; 	vconstnode = constnode;	vconstnode.type = types[TVLONG]; 	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); 	if(0)		com64init(); 	for(i=0; i<nelem(reg); i++) {		reg[i] = 1;		if(i >= D_AX && i <= D_R15 && i != D_SP)			reg[i] = 0;		if(i >= D_X0 && i <= D_X7)			reg[i] = 0;	}} voidgclean(void){	int i;	Sym *s; 	reg[D_SP]--;	for(i=D_AX; i<=D_R15; i++)		if(reg[i])			diag(Z, "reg %R left allocated", i);	for(i=D_X0; i<=D_X7; i++)		if(reg[i])			diag(Z, "reg %R left allocated", i);	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;} intnareg(void){	int i, n; 	n = 0;	for(i=D_AX; i<=D_R15; i++)		if(reg[i] == 0)			n++;	return n;} 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(typesu[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 && typechlpv[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);		gmove(n, tn2);		return;	}	regalloc(tn1, n, Z);	if(n->complex >= FNX) {		cgen(*fnxp, tn1);		(*fnxp)++;	} else		cgen(n, tn1);	regaalloc(tn2, n);	gmove(tn1, tn2);	regfree(tn1);} Node*nodgconst(vlong v, Type *t){	if(!typev[t->etype])		return nodconst((long)v);	vconstnode.vconst = v;	return &vconstnode;} Node*nodconst(long v){	constnode.vconst = v;	return &constnode;} Node*nodfconst(double d){	fconstnode.fconst = d;	return &fconstnode;} intisreg(Node *n, int r){ 	if(n->op == OREGISTER)		if(n->reg == r)			return 1;	return 0;} intnodreg(Node *n, Node *nn, int r){	int et; 	*n = qregnode;	n->reg = r;	if(nn != Z){		et = nn->type->etype;		if(!typefd[et] && nn->type->width <= SZ_LONG && 0)			n->type = typeu[et]? types[TUINT]: types[TINT];		else			n->type = nn->type;//print("nodreg %s [%s]\n", tnames[et], tnames[n->type->etype]);		n->lineno = nn->lineno;	}	if(reg[r] == 0)		return 0;	if(nn != Z) {		if(nn->op == OREGISTER)		if(nn->reg == r)			return 0;	}	return 1;} voidregret(Node *n, Node *nn){	int r; 	r = REGRET;	if(typefd[nn->type->etype])		r = FREGRET;	nodreg(n, nn, r);	reg[r]++;} voidregalloc(Node *n, Node *tn, Node *o){	int i; 	switch(tn->type->etype) {	case TCHAR:	case TUCHAR:	case TSHORT:	case TUSHORT:	case TINT:	case TUINT:	case TLONG:	case TULONG:	case TVLONG:	case TUVLONG:	case TIND:		if(o != Z && o->op == OREGISTER) {			i = o->reg;			if(i >= D_AX && i <= D_R15)				goto out;		}		for(i=D_AX; i<=D_R15; i++)			if(reg[i] == 0)				goto out;		diag(tn, "out of fixed registers");		goto err; 	case TFLOAT:	case TDOUBLE:		if(o != Z && o->op == OREGISTER) {			i = o->reg;			if(i >= D_X0 && i <= D_X7)				goto out;		}		for(i=D_X0; i<=D_X7; i++)			if(reg[i] == 0)				goto out;		diag(tn, "out of float registers");		goto out;	}	diag(tn, "unknown type in regalloc: %T", tn->type);err:	i = 0;out:	if(i)		reg[i]++;	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: %R", 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;	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;} 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 %D", n->op, a);		break; 	case OREGISTER:		a->type = n->reg;		a->sym = S;		break;  	case OIND:		naddr(n->left, a);		if(a->type >= D_AX && a->type <= D_R15)			a->type += D_INDIR;		else		if(a->type == D_CONST)			a->type = D_NONE+D_INDIR;		else		if(a->type == D_ADDR) {			a->type = a->index;			a->index = D_NONE;		} else			goto bad;		break; 	case OINDEX:		a->type = idx.ptr;		if(n->left->op == OADDR || n->left->op == OCONST)			naddr(n->left, a);		if(a->type >= D_AX && a->type <= D_R15)			a->type += D_INDIR;		else		if(a->type == D_CONST)			a->type = D_NONE+D_INDIR;		else		if(a->type == D_ADDR) {			a->type = a->index;			a->index = D_NONE;		} else			goto bad;		a->index = idx.reg;		a->scale = n->scale;		a->offset += n->xoffset;		break; 	case OINDREG:		a->type = n->reg+D_INDIR;		a->sym = S;

Lines 1–500 of 1514.