forsyth20121205-174063a80cc13 years agoHistory
1234 lines · 20.7 KB · C
RawDownload
#include "gc.h" static intcommutes(int o){	switch(o){		case OAND:		case OOR:		case OXOR:		case OLMUL:		case OMUL:		case OADD:			return 1;	}	return 0;} voidcgen(Node *n, Node *nn){	Node *l, *r;	Prog *p1;	Node nod, nod1, nod2, nod3, nod4;	int o, t;	long v, curs; 	if(debug['g'] && nn == Z) {		// prtree(nn, "cgen lhs");		prtree(n, "cgen");	}	if(n == Z || n->type == T)		return;	if(typesuv[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(n->complex >= FNX)	if(l->complex >= FNX)	if(r != Z && r->complex >= FNX)	switch(o) {	default:		regret(&nod, r);		cgen(r, &nod); 		regsalloc(&nod1, r);		gopcode(OAS, &nod, Z, &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;	} 	switch(o) {	default:		diag(n, "unknown op in cgen: %O", o);		break; 	case OAS:		if(l->op == OBIT)			goto bitas;		if(l->addable >= INDEXED && l->complex < FNX) {			if(nn != Z || r->addable < INDEXED) {				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) {			reglcgen(&nod1, l, Z);			if(r->addable >= INDEXED) {				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);		gopcode(OAS, &nod1, Z, &nod2);		bitstore(l, &nod, &nod1, &nod2, nn);		break; 	case OBIT:		if(nn == Z) {			nullwarn(l, Z);			break;		}		bitload(n, &nod, Z, Z, nn);		gopcode(OAS, &nod, Z, nn);		regfree(&nod);		break; 	case ODIV:	case OMOD:		if(nn != Z)		if((t = vlog(r)) >= 0 && t <= 8) {			/* signed div/mod by constant power of 2 */			cgen(l, nn);			gopcode(OGE, nodconst(0), nn, Z);			p1 = p;			if(o == ODIV) {				gopcode(OADD, nodconst((1<<t)-1), Z, nn);				patch(p1, pc);				gopcode(OASHR, nodconst(t), Z, nn);			} else {				gopcode(OSUB, nn, nodconst(0), nn);				regalloc(&nod, l, Z);				gopcode(OAS, nodconst((1<<t)-1), Z, &nod);				gopcode(OAND, &nod, Z, nn);				regfree(&nod);				// gopcode(OAND, nodconst((1<<t)-1), Z, nn);				gopcode(OSUB, nn, nodconst(0), nn);				gbranch(OGOTO);				patch(p1, pc);				p1 = p;				regalloc(&nod, l, Z);				gopcode(OAS, nodconst((1<<t)-1), Z, &nod);				gopcode(OAND, &nod, Z, nn);				regfree(&nod);				// gopcode(OAND, nodconst((1<<t)-1), Z, nn);				patch(p1, pc);			}			break;		}		goto muldiv; 	case OADD:	case OSUB:	case OLSHR:	case OASHL:	case OASHR:		/*		 * immediate operands		 */		if(nn != Z)		if(sconst(r))		if(o == OADD || o == OSUB || r->vconst < (vlong)32) {		// if(r->op == OCONST)		// if(!typefd[n->type->etype]) {			cgen(l, nn);			if(r->vconst == 0)				break;			gopcode(o, r, Z, nn);			break;		} 	case OAND:	case OOR:	case OXOR:	case OLMUL:	case OLDIV:	case OLMOD:	case OMUL:	muldiv:		if(nn == Z) {			nullwarn(l, r);			break;		}		if(o == OMUL || o == OLMUL) {			if(mulcon(n, nn))				break;		}		if(l->complex >= r->complex) {			regalloc(&nod, l, nn);			cgen(l, &nod);			regalloc(&nod1, r, Z);			cgen(r, &nod1);			gopcode(o, &nod1, Z, &nod);		} else {			if(o == OADD || o == OSUB) {				regalloc(&nod, r, nn);				cgen(r, &nod);				regalloc(&nod1, l, Z);				cgen(l, &nod1);				gopcode(o, &nod, &nod1, &nod);			}			else {				if(commutes(o)){					regalloc(&nod, r, nn);					cgen(r, &nod);					regalloc(&nod1, l, Z);					cgen(l, &nod1);					gopcode(o, &nod1, Z, &nod);				}				else{					regalloc(&nod1, r, Z);					cgen(r, &nod1);					regalloc(&nod, l, nn);					cgen(l, &nod);					gopcode(o, &nod1, Z, &nod);				}			}		}		gopcode(OAS, &nod, Z, nn);		regfree(&nod);		regfree(&nod1);		break; /*	case ONEG:		if(nn == Z) {			nullwarn(l, Z);			break;		}		regalloc(&nod, l, nn);		cgen(l, &nod);		gopcode(o, &nod, Z, &nod);		gopcode(OAS, &nod, Z, nn);		regfree(&nod);		break;*/ 	case OASLSHR:	case OASASHL:	case OASASHR:	case OASADD:	case OASSUB:		if(l->op == OBIT)			goto asbitop;		if(sconst(r))		if(o == OASADD || o == OASSUB || r->vconst < (vlong)32) {		// if(r->op == OCONST)		// if(!typefd[n->type->etype]) {			if(l->addable < INDEXED)				reglcgen(&nod2, l, Z);			else				nod2 = *l;			regalloc(&nod, r, nn);			gopcode(OAS, &nod2, Z, &nod);			gopcode(o, r, Z, &nod);			gopcode(OAS, &nod, Z, &nod2);				regfree(&nod);			if(l->addable < INDEXED)				regfree(&nod2);			break;		} 	case OASAND:	case OASXOR:	case OASOR:	case OASLMUL:	case OASLDIV:	case OASLMOD:	case OASMUL:	case OASDIV:	case OASMOD:		if(l->op == OBIT)			goto asbitop;		if(l->complex >= r->complex) {			if(l->addable < INDEXED)				reglcgen(&nod2, l, Z);			else				nod2 = *l;			regalloc(&nod1, r, Z);			cgen(r, &nod1);		} else {			regalloc(&nod1, r, Z);			cgen(r, &nod1);			if(l->addable < INDEXED)				reglcgen(&nod2, l, Z);			else				nod2 = *l;		} 		regalloc(&nod, n, nn);		gmove(&nod2, &nod);		gopcode(o, &nod1, Z, &nod);		gmove(&nod, &nod2);		if(nn != Z)			gopcode(OAS, &nod, Z, nn);		regfree(&nod);		regfree(&nod1);		if(l->addable < INDEXED)			regfree(&nod2);		break; 	asbitop:		regalloc(&nod4, n, nn);		if(l->complex >= r->complex) {			bitload(l, &nod, &nod1, &nod2, &nod4);			regalloc(&nod3, r, Z);			cgen(r, &nod3);		} else {			regalloc(&nod3, r, Z);			cgen(r, &nod3);			bitload(l, &nod, &nod1, &nod2, &nod4);		}		gmove(&nod, &nod4);		gopcode(o, &nod3, Z, &nod4);		regfree(&nod3);		gmove(&nod4, &nod);		regfree(&nod4);		bitstore(l, &nod, &nod1, &nod2, nn);		break; 	case OADDR:		if(nn == Z) {			nullwarn(l, Z);			break;		}		lcgen(l, nn);		break; 	case OFUNC:		if(l->complex >= FNX) {			if(l->op != OIND)				diag(n, "bad function call"); 			regret(&nod, l->left);			cgen(l->left, &nod);			regsalloc(&nod1, l->left);			gopcode(OAS, &nod, Z, &nod1);			regfree(&nod); 			nod = *n;			nod.left = &nod2;			nod2 = *l;			nod2.left = &nod1;			nod2.complex = 1;			cgen(&nod, nn); 			return;		}		if(REGARG >= 0)			o = reg[REGARG];		gargs(r, &nod, &nod1);		if(l->addable < INDEXED) {			reglcgen(&nod, l, Z);			gopcode(OFUNC, Z, Z, &nod);			regfree(&nod);		} else			gopcode(OFUNC, Z, Z, l);		if(REGARG >= 0)			if(o != reg[REGARG])				reg[REGARG]--;		if(nn != Z) {			regret(&nod, n);			gopcode(OAS, &nod, Z, nn);			regfree(&nod);		}		break; 	case OIND:		if(nn == Z) {			nullwarn(l, Z);			break;		}		regialloc(&nod, n, nn);		r = l;		while(r->op == OADD)			r = r->right;		if(sconst(r) && (v = r->vconst+nod.xoffset) >= 0 && v < 32*r->type->width/SZ_LONG) {			v = r->vconst;			r->vconst = 0;			cgen(l, &nod);			nod.xoffset += v;			r->vconst = v;		} else			cgen(l, &nod);		regind(&nod, n);		gopcode(OAS, &nod, Z, nn);		regfree(&nod);		break; 	case OEQ:	case ONE:	case OLE:	case OLT:	case OGE:	case OGT:	case OLO:	case OLS:	case OHI:	case OHS:		if(nn == Z) {			nullwarn(l, r);			break;		}		boolgen(n, 1, nn);		break; 	case OANDAND:	case OOROR:		boolgen(n, 1, nn);		if(nn == Z)			patch(p, pc);		break; 	case ONOT:		if(nn == Z) {			nullwarn(l, Z);			break;		}		boolgen(n, 1, nn);		break; 	case OCOMMA:		cgen(l, Z);		cgen(r, nn);		break; 	case OCAST:		if(nn == Z) {			nullwarn(l, Z);			break;		}		/*		 * convert from types l->n->nn		 */		if(nocast(l->type, n->type)) {			if(nocast(n->type, nn->type)) {				cgen(l, nn);				break;			}		}		regalloc(&nod, l, nn);		cgen(l, &nod);		regalloc(&nod1, n, &nod);		gopcode(OAS, &nod, Z, &nod1);		gopcode(OAS, &nod1, Z, nn);		regfree(&nod1);		regfree(&nod);		break; 	case ODOT:		sugen(l, nodrat, l->type->width);		if(nn != Z) {			warn(n, "non-interruptable temporary");			nod = *nodrat;			if(!r || r->op != OCONST) {				diag(n, "DOT and no offset");				break;			}			nod.xoffset += (long)r->vconst;			nod.type = n->type;			cgen(&nod, nn);		}		break; 	case OCOND:

Lines 1–500 of 1234.