cgen.c

来自「这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易」· C语言 代码 · 共 1,165 行 · 第 1/2 页

C
1,165
字号
			regind(t, n);			return;		}	} else if(n->op == OINDREG) {		if((v = n->xoffset) > -4096 && v < 4096) {			n->op = OREGISTER;			cgen(n, t);			t->xoffset += v;			n->op = OINDREG;			regind(t, n);			return;		}	}	lcgen(n, t);	regind(t, n);}voidreglpcgen(Node *n, Node *nn, int f){	Type *t;	t = nn->type;	nn->type = types[TLONG];	if(f)		reglcgen(n, nn, Z);	else {		regialloc(n, nn, Z);		lcgen(nn, n);		regind(n, nn);	}	nn->type = t;}voidlcgen(Node *n, Node *nn){	Prog *p1;	Node nod;	if(debug['g']) {		prtree(nn, "lcgen lhs");		prtree(n, "lcgen");	}	if(n == Z || n->type == T)		return;	if(nn == Z) {		nn = &nod;		regalloc(&nod, n, Z);	}	switch(n->op) {	default:		if(n->addable < INDEXED) {			diag(n, "unknown op in lcgen: %O", n->op);			break;		}		nod = *n;		nod.op = OADDR;		nod.left = n;		nod.right = Z;		nod.type = types[TIND];		gopcode(OAS, &nod, Z, nn);		break;	case OCOMMA:		cgen(n->left, n->left);		lcgen(n->right, nn);		break;	case OIND:		cgen(n->left, nn);		break;	case OCOND:		bcgen(n->left, 1);		p1 = p;		lcgen(n->right->left, nn);		gbranch(OGOTO);		patch(p1, pc);		p1 = p;		lcgen(n->right->right, nn);		patch(p1, pc);		break;	}}voidbcgen(Node *n, int true){	if(n->type == T)		gbranch(OGOTO);	else		boolgen(n, true, Z);}voidboolgen(Node *n, int true, Node *nn){	int o;	Prog *p1, *p2;	Node *l, *r, nod, nod1;	long curs;	if(debug['g']) {		prtree(nn, "boolgen lhs");		prtree(n, "boolgen");	}	curs = cursafe;	l = n->left;	r = n->right;	switch(n->op) {	default:		regalloc(&nod, n, nn);		cgen(n, &nod);		o = ONE;		if(true)			o = comrel[relindex(o)];		if(typefd[n->type->etype]) {			gopcode(o, nodfconst(0), &nod, Z);		} else			gopcode(o, nodconst(0), &nod, Z);		regfree(&nod);		goto com;	case OCONST:		o = vconst(n);		if(!true)			o = !o;		gbranch(OGOTO);		if(o) {			p1 = p;			gbranch(OGOTO);			patch(p1, pc);		}		goto com;	case OCOMMA:		cgen(l, Z);		boolgen(r, true, nn);		break;	case ONOT:		boolgen(l, !true, nn);		break;	case OCOND:		bcgen(l, 1);		p1 = p;		bcgen(r->left, true);		p2 = p;		gbranch(OGOTO);		patch(p1, pc);		p1 = p;		bcgen(r->right, !true);		patch(p2, pc);		p2 = p;		gbranch(OGOTO);		patch(p1, pc);		patch(p2, pc);		goto com;	case OANDAND:		if(!true)			goto caseor;	caseand:		bcgen(l, true);		p1 = p;		bcgen(r, !true);		p2 = p;		patch(p1, pc);		gbranch(OGOTO);		patch(p2, pc);		goto com;	case OOROR:		if(!true)			goto caseand;	caseor:		bcgen(l, !true);		p1 = p;		bcgen(r, !true);		p2 = p;		gbranch(OGOTO);		patch(p1, pc);		patch(p2, pc);		goto com;	case OEQ:	case ONE:	case OLE:	case OLT:	case OGE:	case OGT:	case OHI:	case OHS:	case OLO:	case OLS:		o = n->op;		if(true)			o = comrel[relindex(o)];		if(l->complex >= FNX && r->complex >= FNX) {			regret(&nod, r);			cgenrel(r, &nod, 1);			regsalloc(&nod1, r);			gopcode(OAS, &nod, Z, &nod1);			regfree(&nod);			nod = *n;			nod.right = &nod1;			boolgen(&nod, true, nn);			break;		}		if(sconst(l)) {			regalloc(&nod, r, nn);			cgenrel(r, &nod, 1);			o = invrel[relindex(o)];			gopcode(o, l, &nod, Z);			regfree(&nod);			goto com;		}		if(sconst(r)) {			regalloc(&nod, l, nn);			cgenrel(l, &nod, 1);			gopcode(o, r, &nod, Z);			regfree(&nod);			goto com;		}		if(l->complex >= r->complex) {			regalloc(&nod1, l, nn);			cgenrel(l, &nod1, 1);			regalloc(&nod, r, Z);			cgenrel(r, &nod, 1);		} else {			regalloc(&nod, r, nn);			cgenrel(r, &nod, 1);			regalloc(&nod1, l, Z);			cgenrel(l, &nod1, 1);		}		gopcode(o, &nod, &nod1, Z);		regfree(&nod);		regfree(&nod1);	com:		if(nn != Z) {			p1 = p;			gopcode(OAS, nodconst(1), Z, nn);			gbranch(OGOTO);			p2 = p;			patch(p1, pc);			gopcode(OAS, nodconst(0), Z, nn);			patch(p2, pc);		}		break;	}	cursafe = curs;}voidsugen(Node *n, Node *nn, long w){	Prog *p1;	Node nod0, nod1, nod2, nod3, nod4, *l, *r;	Type *t;	long pc1;	int i, m, c;	if(n == Z || n->type == T)		return;	if(debug['g']) {		prtree(nn, "sugen lhs");		prtree(n, "sugen");	}	if(nn == nodrat)		if(w > nrathole)			nrathole = w;	switch(n->op) {	case OIND:		if(nn == Z) {			nullwarn(n->left, Z);			break;		}	default:		goto copy;	case OCONST:		if(n->type && typev[n->type->etype]) {			if(nn == Z) {				nullwarn(n->left, Z);				break;			}			t = nn->type;			nn->type = types[TLONG];			reglcgen(&nod1, nn, Z);			nn->type = t;			if(align(0, types[TCHAR], Aarg1))	/* isbigendian */				gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);			else				gopcode(OAS, nod32const(n->vconst), Z, &nod1);			nod1.xoffset += SZ_LONG;			if(align(0, types[TCHAR], Aarg1))	/* isbigendian */				gopcode(OAS, nod32const(n->vconst), Z, &nod1);			else				gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);			regfree(&nod1);			break;		}		goto copy;	case ODOT:		l = n->left;		sugen(l, nodrat, l->type->width);		if(nn != Z) {			warn(n, "non-interruptable temporary");			nod1 = *nodrat;			r = n->right;			if(!r || r->op != OCONST) {				diag(n, "DOT and no offset");				break;			}			nod1.xoffset += (long)r->vconst;			nod1.type = n->type;			sugen(&nod1, nn, w);		}		break;	case OSTRUCT:		/*		 * rewrite so lhs has no fn call		 */		if(nn != Z && nn->complex >= FNX) {			nod1 = *n;			nod1.type = typ(TIND, n->type);			regret(&nod2, &nod1);			lcgen(nn, &nod2);			regsalloc(&nod0, &nod1);			gopcode(OAS, &nod2, Z, &nod0);			regfree(&nod2);			nod1 = *n;			nod1.op = OIND;			nod1.left = &nod0;			nod1.right = Z;			nod1.complex = 1;			sugen(n, &nod1, w);			return;		}		r = n->left;		for(t = n->type->link; t != T; t = t->down) {			l = r;			if(r->op == OLIST) {				l = r->left;				r = r->right;			}			if(nn == Z) {				cgen(l, nn);				continue;			}			/*			 * hand craft *(&nn + o) = l			 */			nod0 = znode;			nod0.op = OAS;			nod0.type = t;			nod0.left = &nod1;			nod0.right = l;			nod1 = znode;			nod1.op = OIND;			nod1.type = t;			nod1.left = &nod2;			nod2 = znode;			nod2.op = OADD;			nod2.type = typ(TIND, t);			nod2.left = &nod3;			nod2.right = &nod4;			nod3 = znode;			nod3.op = OADDR;			nod3.type = nod2.type;			nod3.left = nn;			nod4 = znode;			nod4.op = OCONST;			nod4.type = nod2.type;			nod4.vconst = t->offset;			ccom(&nod0);			acom(&nod0);			xcom(&nod0);			nod0.addable = 0;			cgen(&nod0, Z);		}		break;	case OAS:		if(nn == Z) {			if(n->addable < INDEXED)				sugen(n->right, n->left, w);			break;		}		sugen(n->right, nodrat, w);		warn(n, "non-interruptable temporary");		sugen(nodrat, n->left, w);		sugen(nodrat, nn, w);		break;	case OFUNC:		if(nn == Z) {			sugen(n, nodrat, w);			break;		}		if(nn->op != OIND) {			nn = new1(OADDR, nn, Z);			nn->type = types[TIND];			nn->addable = 0;		} else			nn = nn->left;		n = new(OFUNC, n->left, new(OLIST, nn, n->right));		n->type = types[TVOID];		n->left->type = types[TVOID];		cgen(n, Z);		break;	case OCOND:		bcgen(n->left, 1);		p1 = p;		sugen(n->right->left, nn, w);		gbranch(OGOTO);		patch(p1, pc);		p1 = p;		sugen(n->right->right, nn, w);		patch(p1, pc);		break;	case OCOMMA:		cgen(n->left, Z);		sugen(n->right, nn, w);		break;	}	return;copy:	if(nn == Z)		return;	if(n->complex >= FNX && nn->complex >= FNX) {		t = nn->type;		nn->type = types[TLONG];		regialloc(&nod1, nn, Z);		lcgen(nn, &nod1);		regsalloc(&nod2, nn);		nn->type = t;		gopcode(OAS, &nod1, Z, &nod2);		regfree(&nod1);		nod2.type = typ(TIND, t);		nod1 = nod2;		nod1.op = OIND;		nod1.left = &nod2;		nod1.right = Z;		nod1.complex = 1;		nod1.type = t;		sugen(n, &nod1, w);		return;	}	w /= SZ_LONG;	if(w <= 2) {		if(n->complex > nn->complex) {			reglpcgen(&nod1, n, 1);			reglpcgen(&nod2, nn, 1);		} else {			reglpcgen(&nod2, nn, 1);			reglpcgen(&nod1, n, 1);		}		regalloc(&nod3, &regnode, Z);		regalloc(&nod4, &regnode, Z);		nod0 = *nodconst((1<<nod3.reg)|(1<<nod4.reg));		if(w == 2 && nod1.xoffset == 0)			gmovm(&nod1, &nod0, 0);		else {			gmove(&nod1, &nod3);			if(w == 2) {				nod1.xoffset += SZ_LONG;				gmove(&nod1, &nod4);			}		}		if(w == 2 && nod2.xoffset == 0)			gmovm(&nod0, &nod2, 0);		else {			gmove(&nod3, &nod2);			if(w == 2) {				nod2.xoffset += SZ_LONG;				gmove(&nod4, &nod2);			}		}		regfree(&nod1);		regfree(&nod2);		regfree(&nod3);		regfree(&nod4);		return;	}	if(n->complex > nn->complex) {		reglpcgen(&nod1, n, 0);		reglpcgen(&nod2, nn, 0);	} else {		reglpcgen(&nod2, nn, 0);		reglpcgen(&nod1, n, 0);	}	m = 0;	for(c = 0; c < w && c < 4; c++) {		i = tmpreg();		if (i == 0)			break;		reg[i]++;		m |= 1<<i;	}	nod4 = *(nodconst(m));	if(w < 3*c) {		for (; w>c; w-=c) {			gmovm(&nod1, &nod4, 1);			gmovm(&nod4, &nod2, 1);		}		goto out;	}	regalloc(&nod3, &regnode, Z);	gopcode(OAS, nodconst(w/c), Z, &nod3);	w %= c;		pc1 = pc;	gmovm(&nod1, &nod4, 1);	gmovm(&nod4, &nod2, 1);	gopcode(OSUB, nodconst(1), Z, &nod3);	gopcode(OEQ, nodconst(0), &nod3, Z);	p->as = ABGT;	patch(p, pc1);	regfree(&nod3);out:	if (w) {		i = 0;		while (c>w) {			while ((m&(1<<i)) == 0)				i++;			m &= ~(1<<i);			reg[i] = 0;			c--;			i++;		}		nod4.vconst = m;		gmovm(&nod1, &nod4, 0);		gmovm(&nod4, &nod2, 0);	}	i = 0;	do {		while ((m&(1<<i)) == 0)			i++;		reg[i] = 0;		c--;		i++;	} while (c>0);	regfree(&nod1);	regfree(&nod2);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?