forsyth20121205-174063a80cc13 years agoHistory
1941 lines · 33.3 KB · C
RawDownload
#include "gc.h" /* ,x/^(print|prtree)\(/i/\/\/ */int castup(Type*, Type*); voidcgen(Node *n, Node *nn){	Node *l, *r, *t;	Prog *p1;	Node nod, nod1, nod2, nod3, nod4;	int o, hardleft;	long v, curs;	vlong c; 	if(debug['g']) {		prtree(nn, "cgen lhs");		prtree(n, "cgen");	}	if(n == Z || n->type == T)		return;	if(typesu[n->type->etype]) {		sugen(n, nn, n->type->width);		return;	}	l = n->left;	r = n->right;	o = n->op;	if(n->addable >= INDEXED) {		if(nn == Z) {			switch(o) {			default:				nullwarn(Z, Z);				break;			case OINDEX:				nullwarn(l, r);				break;			}			return;		}		gmove(n, nn);		return;	}	curs = cursafe; 	if(l->complex >= FNX)	if(r != Z && r->complex >= FNX)	switch(o) {	default:		if(cond(o) && typesu[l->type->etype])			break; 		regret(&nod, r);		cgen(r, &nod); 		regsalloc(&nod1, r);		gmove(&nod, &nod1); 		regfree(&nod);		nod = *n;		nod.right = &nod1; 		cgen(&nod, nn);		return; 	case OFUNC:	case OCOMMA:	case OANDAND:	case OOROR:	case OCOND:	case ODOT:		break;	} 	hardleft = l->addable < INDEXED || l->complex >= FNX;	switch(o) {	default:		diag(n, "unknown op in cgen: %O", o);		break; 	case ONEG:	case OCOM:		if(nn == Z) {			nullwarn(l, Z);			break;		}		regalloc(&nod, l, nn);		cgen(l, &nod);		gopcode(o, n->type, Z, &nod);		gmove(&nod, nn);		regfree(&nod);		break; 	case OAS:		if(l->op == OBIT)			goto bitas;		if(!hardleft) {			if(nn != Z || r->addable < INDEXED || hardconst(r)) {				if(r->complex >= FNX && nn == Z)					regret(&nod, r);				else					regalloc(&nod, r, nn);				cgen(r, &nod);				gmove(&nod, l);				if(nn != Z)					gmove(&nod, nn);				regfree(&nod);			} else				gmove(r, l);			break;		}		if(l->complex >= r->complex) {			if(l->op == OINDEX && immconst(r)) {				gmove(r, l);				break;			}			reglcgen(&nod1, l, Z);			if(r->addable >= INDEXED && !hardconst(r)) {				gmove(r, &nod1);				if(nn != Z)					gmove(r, nn);				regfree(&nod1);				break;			}			regalloc(&nod, r, nn);			cgen(r, &nod);		} else {			regalloc(&nod, r, nn);			cgen(r, &nod);			reglcgen(&nod1, l, Z);		}		gmove(&nod, &nod1);		regfree(&nod);		regfree(&nod1);		break; 	bitas:		n = l->left;		regalloc(&nod, r, nn);		if(l->complex >= r->complex) {			reglcgen(&nod1, n, Z);			cgen(r, &nod);		} else {			cgen(r, &nod);			reglcgen(&nod1, n, Z);		}		regalloc(&nod2, n, Z);		gmove(&nod1, &nod2);		bitstore(l, &nod, &nod1, &nod2, nn);		break; 	case OBIT:		if(nn == Z) {			nullwarn(l, Z);			break;		}		bitload(n, &nod, Z, Z, nn);		gmove(&nod, nn);		regfree(&nod);		break; 	case OLSHR:	case OASHL:	case OASHR:		if(nn == Z) {			nullwarn(l, r);			break;		}		if(r->op == OCONST) {			if(r->vconst == 0) {				cgen(l, nn);				break;			}			regalloc(&nod, l, nn);			cgen(l, &nod);			if(o == OASHL && r->vconst == 1)				gopcode(OADD, n->type, &nod, &nod);			else				gopcode(o, n->type, r, &nod);			gmove(&nod, nn);			regfree(&nod);			break;		} 		/*		 * get nod to be D_CX		 */		if(nodreg(&nod, nn, D_CX)) {			regsalloc(&nod1, n);			gmove(&nod, &nod1);			cgen(n, &nod);		/* probably a bug */			gmove(&nod, nn);			gmove(&nod1, &nod);			break;		}		reg[D_CX]++;		if(nn->op == OREGISTER && nn->reg == D_CX)			regalloc(&nod1, l, Z);		else			regalloc(&nod1, l, nn);		if(r->complex >= l->complex) {			cgen(r, &nod);			cgen(l, &nod1);		} else {			cgen(l, &nod1);			cgen(r, &nod);		}		gopcode(o, n->type, &nod, &nod1);		gmove(&nod1, nn);		regfree(&nod);		regfree(&nod1);		break; 	case OADD:	case OSUB:	case OOR:	case OXOR:	case OAND:		if(nn == Z) {			nullwarn(l, r);			break;		}		if(typefd[n->type->etype])			goto fop;		if(r->op == OCONST) {			if(r->vconst == 0 && o != OAND) {				cgen(l, nn);				break;			}		}		if(n->op == OADD && l->op == OASHL && l->right->op == OCONST		&& (r->op != OCONST || r->vconst < -128 || r->vconst > 127)) {			c = l->right->vconst;			if(c > 0 && c <= 3) {				if(l->left->complex >= r->complex) {					regalloc(&nod, l->left, nn);					cgen(l->left, &nod);					if(r->addable < INDEXED) {						regalloc(&nod1, r, Z);						cgen(r, &nod1);						genmuladd(&nod, &nod, 1 << c, &nod1);						regfree(&nod1);					}					else						genmuladd(&nod, &nod, 1 << c, r);				}				else {					regalloc(&nod, r, nn);					cgen(r, &nod);					regalloc(&nod1, l->left, Z);					cgen(l->left, &nod1);					genmuladd(&nod, &nod1, 1 << c, &nod);					regfree(&nod1);				}				gmove(&nod, nn);				regfree(&nod);				break;			}		}		if(r->addable >= INDEXED && !hardconst(r)) {			regalloc(&nod, l, nn);			cgen(l, &nod);			gopcode(o, n->type, r, &nod);			gmove(&nod, nn);			regfree(&nod);			break;		}		if(l->complex >= r->complex) {			regalloc(&nod, l, nn);			cgen(l, &nod);			regalloc(&nod1, r, Z);			cgen(r, &nod1);			gopcode(o, n->type, &nod1, &nod);		} else {			regalloc(&nod1, r, nn);			cgen(r, &nod1);			regalloc(&nod, l, Z);			cgen(l, &nod);			gopcode(o, n->type, &nod1, &nod);		}		gmove(&nod, nn);		regfree(&nod);		regfree(&nod1);		break; 	case OLMOD:	case OMOD:	case OLMUL:	case OLDIV:	case OMUL:	case ODIV:		if(nn == Z) {			nullwarn(l, r);			break;		}		if(typefd[n->type->etype])			goto fop;		if(r->op == OCONST && typechl[n->type->etype]) {	/* TO DO */			SET(v);			switch(o) {			case ODIV:			case OMOD:				c = r->vconst;				if(c < 0)					c = -c;				v = log2(c);				if(v < 0)					break;				/* fall thru */			case OMUL:			case OLMUL:				regalloc(&nod, l, nn);				cgen(l, &nod);				switch(o) {				case OMUL:				case OLMUL:					mulgen(n->type, r, &nod);					break;				case ODIV:					sdiv2(r->vconst, v, l, &nod);					break;				case OMOD:					smod2(r->vconst, v, l, &nod);					break;				}				gmove(&nod, nn);				regfree(&nod);				goto done;			case OLDIV:				c = r->vconst;				if((c & 0x80000000) == 0)					break;				regalloc(&nod1, l, Z);				cgen(l, &nod1);				regalloc(&nod, l, nn);				zeroregm(&nod);				gins(ACMPL, &nod1, nodconst(c));				gins(ASBBL, nodconst(-1), &nod);				regfree(&nod1);				gmove(&nod, nn);				regfree(&nod);				goto done;			}		} 		if(o == OMUL) {			if(l->addable >= INDEXED) {				t = l;				l = r;				r = t;			}			/* should favour AX */			regalloc(&nod, l, nn);			cgen(l, &nod);			if(r->addable < INDEXED || hardconst(r)) {				regalloc(&nod1, r, Z);				cgen(r, &nod1);				gopcode(OMUL, n->type, &nod1, &nod);				regfree(&nod1);			}else				gopcode(OMUL, n->type, r, &nod);	/* addressible */			gmove(&nod, nn);			regfree(&nod);			break;		} 		/*		 * get nod to be D_AX		 * get nod1 to be D_DX		 */		if(nodreg(&nod, nn, D_AX)) {			regsalloc(&nod2, n);			gmove(&nod, &nod2);			v = reg[D_AX];			reg[D_AX] = 0; 			if(isreg(l, D_AX)) {				nod3 = *n;				nod3.left = &nod2;				cgen(&nod3, nn);			} else			if(isreg(r, D_AX)) {				nod3 = *n;				nod3.right = &nod2;				cgen(&nod3, nn);			} else				cgen(n, nn); 			gmove(&nod2, &nod);			reg[D_AX] = v;			break;		}		if(nodreg(&nod1, nn, D_DX)) {			regsalloc(&nod2, n);			gmove(&nod1, &nod2);			v = reg[D_DX];			reg[D_DX] = 0; 			if(isreg(l, D_DX)) {				nod3 = *n;				nod3.left = &nod2;				cgen(&nod3, nn);			} else			if(isreg(r, D_DX)) {				nod3 = *n;				nod3.right = &nod2;				cgen(&nod3, nn);			} else				cgen(n, nn); 			gmove(&nod2, &nod1);			reg[D_DX] = v;			break;		}		reg[D_AX]++; 		if(r->op == OCONST && (o == ODIV || o == OLDIV) && immconst(r) && typechl[r->type->etype]) {			reg[D_DX]++;			if(l->addable < INDEXED) {				regalloc(&nod2, l, Z);				cgen(l, &nod2);				l = &nod2;			}			if(o == ODIV)				sdivgen(l, r, &nod, &nod1);			else				udivgen(l, r, &nod, &nod1);			gmove(&nod1, nn);			if(l == &nod2)				regfree(l);			goto freeaxdx;		} 		if(l->complex >= r->complex) {			cgen(l, &nod);			reg[D_DX]++;			if(o == ODIV || o == OMOD)				gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);			if(o == OLDIV || o == OLMOD)				zeroregm(&nod1);			if(r->addable < INDEXED || r->op == OCONST) {				regsalloc(&nod3, r);				cgen(r, &nod3);				gopcode(o, n->type, &nod3, Z);			} else				gopcode(o, n->type, r, Z);		} else {			regsalloc(&nod3, r);			cgen(r, &nod3);			cgen(l, &nod);			reg[D_DX]++;			if(o == ODIV || o == OMOD)				gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);			if(o == OLDIV || o == OLMOD)				zeroregm(&nod1);			gopcode(o, n->type, &nod3, Z);		}		if(o == OMOD || o == OLMOD)			gmove(&nod1, nn);		else			gmove(&nod, nn);	freeaxdx:		regfree(&nod);		regfree(&nod1);		break; 	case OASLSHR:	case OASASHL:	case OASASHR:		if(r->op == OCONST)			goto asand;		if(l->op == OBIT)			goto asbitop;		if(typefd[n->type->etype])			goto asand;	/* can this happen? */ 		/*		 * get nod to be D_CX		 */		if(nodreg(&nod, nn, D_CX)) {			regsalloc(&nod1, n);			gmove(&nod, &nod1);			cgen(n, &nod);			if(nn != Z)				gmove(&nod, nn);			gmove(&nod1, &nod);			break;		}		reg[D_CX]++; 		if(r->complex >= l->complex) {			cgen(r, &nod);			if(hardleft)				reglcgen(&nod1, l, Z);			else				nod1 = *l;		} else {			if(hardleft)				reglcgen(&nod1, l, Z);			else

Lines 1–500 of 1941.