Charles.Forsyth20060303644188019 years agoHistory
819 lines · 12.4 KB · C
RawDownload
#include "gc.h" voidcodgen(Node *n, Node *nn){	Prog *sp; 	argoff = 0;	inargs = 0;	for(;; nn = nn->left) {		if(nn == Z) {			diag(Z, "cant find function name");			return;		}		if(nn->op == ONAME)			break;	}	nearln = nn->lineno;	gpseudo(ATEXT, nn->sym, D_CONST, stkoff);	sp = p; 	retok = 0;	gen(n);	if(!retok)		if(thisfn->link->etype != TVOID)			warn(Z, "no return at end of function: %s", nn->sym->name); 	noretval(3);	gbranch(ORETURN);	if(!debug['N'] || debug['R'] || debug['P'])		regopt(sp);} voidgen(Node *n){	Node *l;	Prog *sp, *spc, *spb;	Case *cn;	long sbc, scc;	int g, o; loop:	if(n == Z)		return;	nearln = n->lineno;	o = n->op;	if(debug['G'])		if(o != OLIST)			print("%L %O\n", nearln, o); 	retok = 0;	switch(o) { 	default:		complex(n);		doinc(n, PRE);		cgen(n, D_NONE, n);		doinc(n, POST);		break; 	case OLIST:		gen(n->left); 	rloop:		n = n->right;		goto loop; 	case ORETURN:		retok = 1;		complex(n);		if(n->type == T)			break;		l = n->left;		if(l == Z) {			noretval(3);			gbranch(ORETURN);			break;		}		doinc(l, PRE);		if(typesuv[n->type->etype]) {			sugen(l, D_TREE, nodret, n->type->width);			doinc(l, POST);			noretval(3);			gbranch(ORETURN);			break;		}		g = regalloc(n->type, regret(n->type));		cgen(l, g, n);		doinc(l, POST);		if(typefd[n->type->etype])			noretval(1);		else			noretval(2);		gbranch(ORETURN);		regfree(g);		break; 	case OLABEL:		l = n->left;		if(l) {			l->xoffset = pc;			if(l->label)				patch(l->label, pc);		}		gbranch(OGOTO);	/* prevent self reference in reg */		patch(p, pc);		goto rloop; 	case OGOTO:		retok = 1;		n = n->left;		if(n == Z)			return;		if(n->complex == 0) {			diag(Z, "label undefined: %s", n->sym->name);			return;		}		gbranch(OGOTO);		if(n->xoffset) {			patch(p, n->xoffset);			return;		}		if(n->label)			patch(n->label, pc-1);		n->label = p;		return; 	case OCASE:		l = n->left;		if(cases == C)			diag(n, "case/default outside a switch");		if(l == Z) {			cas();			cases->val = 0;			cases->def = 1;			cases->label = pc;			setsp();;			goto rloop;		}		complex(l);		if(l->type == T)			goto rloop;		if(l->op == OCONST)		if(typechl[l->type->etype]) {			cas();			cases->val = l->vconst;			cases->def = 0;			cases->label = pc;			setsp();			goto rloop;		}		diag(n, "case expression must be integer constant");		goto rloop; 	case OSWITCH:		l = n->left;		complex(l);		doinc(l, PRE);		if(l->type == T)			break;		if(!typechl[l->type->etype]) {			diag(n, "switch expression must be integer");			break;		}		g = regalloc(types[TLONG], D_NONE);		n->type = types[TLONG];		cgen(l, g, n);		regfree(g);		doinc(l, POST);		setsp();		gbranch(OGOTO);		/* entry */		sp = p; 		cn = cases;		cases = C;		cas(); 		sbc = breakpc;		breakpc = pc;		gbranch(OGOTO);		spb = p; 		gen(n->right);		gbranch(OGOTO);		patch(p, breakpc); 		patch(sp, pc);		doswit(g, l); 		patch(spb, pc);		cases = cn;		breakpc = sbc;		setsp();		break; 	case OWHILE:	case ODWHILE:		l = n->left;		gbranch(OGOTO);		/* entry */		sp = p; 		scc = continpc;		continpc = pc;		gbranch(OGOTO);		spc = p; 		sbc = breakpc;		breakpc = pc;		gbranch(OGOTO);		spb = p; 		patch(spc, pc);		if(n->op == OWHILE)			patch(sp, pc);		bcomplex(l);	/* test */		patch(p, breakpc); 		if(n->op == ODWHILE)			patch(sp, pc);		gen(n->right);		/* body */		gbranch(OGOTO);		patch(p, continpc); 		patch(spb, pc);		continpc = scc;		breakpc = sbc;		break; 	case OFOR:		l = n->left;		gen(l->right->left);	/* init */		gbranch(OGOTO);			/* entry */		sp = p; 		scc = continpc;		continpc = pc;		gbranch(OGOTO);		spc = p; 		sbc = breakpc;		breakpc = pc;		gbranch(OGOTO);		spb = p; 		patch(spc, pc);		gen(l->right->right);	/* inc */		patch(sp, pc);			if(l->left != Z) {	/* test */			bcomplex(l->left);			patch(p, breakpc);		}		gen(n->right);		/* body */		gbranch(OGOTO);		patch(p, continpc); 		patch(spb, pc);		continpc = scc;		breakpc = sbc;		break; 	case OCONTINUE:		if(continpc < 0) {			diag(n, "continue not in a loop");			break;		}		gbranch(OGOTO);		patch(p, continpc);		break; 	case OBREAK:		if(breakpc < 0) {			diag(n, "break not in a loop");			break;		}		gbranch(OGOTO);		patch(p, breakpc);		break; 	case OIF:		l = n->left;		bcomplex(l);		sp = p;		if(n->right->left != Z)			gen(n->right->left);		if(n->right->right != Z) {			gbranch(OGOTO);			patch(sp, pc);			sp = p;			gen(n->right->right);		}		patch(sp, pc);		break; 	case OSET:	case OUSED:		usedset(n->left, o);		break;	}} voidusedset(Node *n, int o){	if(n->op == OLIST) {		usedset(n->left, o);		usedset(n->right, o);		return;	}	complex(n);	switch(n->op) {	case OADDR:	/* volatile */		gopcode(OTST, types[TINT], D_TREE, n, D_NONE, Z);		p->as = ANOP;		break;	case ONAME:		if(o == OSET)			gopcode(OTST, types[TINT], D_NONE, Z, D_TREE, n);		else			gopcode(OTST, types[TINT], D_TREE, n, D_NONE, Z);		p->as = ANOP;		break;	}} voidnoretval(int n){ 	if(n & 1) {		gopcode(OTST, types[TINT], D_NONE, Z, regret(types[TLONG]), Z);		p->as = ANOP;	}	if(n & 2) {		gopcode(OTST, types[TINT], D_NONE, Z, regret(types[TDOUBLE]), Z);		p->as = ANOP;	}} /* *	calculate addressability as follows *		REGISTER ==> 12		register *		NAME ==> 10/11		name+value(SB/SP) *		CONST ==> 20		$value *		*(20) ==> 21		value *		&(10) ==> 12		$name+value(SB) *		&(11) ==> 1		$name+value(SP) *		(12) + (20) ==> 12	fold constants *		(1) + (20) ==> 1	fold constants *		*(12) ==> 10		back to name *		*(1) ==> 11		back to name * *		(2,10,11) + (20) ==> 2	indirect w offset *		(2) ==> &13 *		*(10,11) ==> 13		indirect, no index * *		(20) * (X) ==> 7	multiplier in indexing *		(X,7) + (12,1) ==> 8	adder in indexing (addresses) *		(X,7) + (10,11,2) ==> 8	adder in indexing (names) *		(8) ==> &9		index, almost addressable * *		(X)++ ==> X		fake addressability * *	calculate complexity (number of registers) */voidxcom(Node *n){	Node *l, *r;	int g; 	if(n == Z)		return;	l = n->left;	r = n->right;	n->complex = 0;	n->addable = 0;	switch(n->op) {	case OCONST:		n->addable = 20;		break; 	case ONAME:		n->addable = 10;		if(n->class == CPARAM || n->class == CAUTO)			n->addable = 11;		break; 	case OREGISTER:		n->addable = 12;		break; 	case OADDR:		xcom(l);		if(l->addable == 10)			n->addable = 12;		else		if(l->addable == 11)			n->addable = 1;		break; 	case OADD:		xcom(l);		xcom(r);		if(n->type->etype != TIND)			break; 		if(l->addable == 20)		switch(r->addable) {		case 12:		case 1:			n->addable = r->addable;			goto brk;		case 10:		case 11:		case 2:			goto addr13;		}		if(r->addable == 20)		switch(l->addable) {		case 12:		case 1:			n->addable = l->addable;			goto brk;		case 10:		case 11:		case 2:		addr13:			n->addable = 2;			l = new1(OXXX, Z, Z);			*l = *n;			n->op = OIND;			n->left = l;			n->right = Z;			n->addable = 13;			l = new1(OXXX, Z, Z);			*l = *n;			n->op = OADDR;			n->left = l;			n->right = Z;			n->addable = 2;			goto brk;		} 		switch(r->addable) {		case 10:		case 11:		case 12:		case 1:			n->addable = 8;		}		switch(l->addable) {		case 10:		case 11:		case 12:		case 1:			n->addable = 8;		}		if(n->addable == 8) {			indx(n);			l = new1(OINDEX, idx.basetree, idx.regtree);			l->scale = idx.scale;			l->addable = 9;			l->complex = l->right->complex;			l->type = l->left->type;			n->op = OADDR;			n->left = l;			n->right = Z;			n->addable = 0;			break;		}		break; 	case OIND:		xcom(l);		if(l->op == OADDR) {			l = l->left;			l->type = n->type;			*n = *l;			return;		}		switch(l->addable) {		case 20:			n->addable = 21;			break;		case 1:			n->addable = 11;			break;		case 12:			n->addable = 10;			break;		case 10:		case 11:		case 2:			n->addable = 13;			break;		}		break; 	case OASHL:

Lines 1–500 of 819.