⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cgen.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "gc.h"voidcgen(Node *n, int result, Node *nn){	Node *l, *r, nod;	int lg, rg, xg, yg, g, o;	long v;	Prog *p1;	if(n == Z || n->type == T)		return;	if(typesuv[n->type->etype]) {		sugen(n, result, nn, n->type->width);		return;	}	if(debug['g']) {		if(result == D_TREE)			prtree(nn, "result");		else			print("result = %R\n", result);		prtree(n, "cgen");	}	l = n->left;	r = n->right;	o = n->op;	if(n->addable >= INDEXED) {		if(result == D_NONE) {			if(nn == Z)				switch(o) {				default:					nullwarn(Z, Z);					break;				case OINDEX:					nullwarn(l, r);					break;				}			return;		}		gmove(n->type, nn->type, D_TREE, n, result, nn);		return;	}	v = 0; /* set */	switch(o) {	default:		diag(n, "unknown op in cgen: %O", o);		break;	case OAS:		if(l->op == OBIT)			goto bitas;		/*		 * recursive use of result		 */		if(result == D_NONE)		if(l->addable > INDEXED)		if(l->complex < FNX) {			cgen(r, D_TREE, l);			break;		}		/*		 * function calls on both sides		 */		if(l->complex >= FNX && r->complex >= FNX) {			cgen(r, D_TOS, r);			v = argoff;			lg = regaddr(result);			lcgen(l, lg, Z);			lg |= I_INDIR;			adjsp(v - argoff);			gmove(r->type, l->type, D_TOS, r, lg, l);			if(result != D_NONE)				gmove(l->type, nn->type, lg, l, result, nn);			regfree(lg);			break;		}		rg = D_TREE;		lg = D_TREE;		if(r->complex >= l->complex) {			/*			 * right side before left			 */			if(result != D_NONE) {				rg = regalloc(n->type, result);				cgen(r, rg, n);			} else			if(r->complex >= FNX || r->addable < INDEXED) {				rg = regalloc(r->type, result);				cgen(r, rg, r);			}			if(l->addable < INDEXED) {				lg = regaddr(lg);				lcgen(l, lg, Z);				lg |= I_INDIR;			}		} else {			/*			 * left before right			 */			if(l->complex >= FNX || l->addable < INDEXED) {				lg = regaddr(lg);				lcgen(l, lg, Z);				lg |= I_INDIR;			}			if(result != D_NONE) {				rg = regalloc(n->type, result);				cgen(r, rg, n);			} else			if(r->addable < INDEXED) {				rg = regalloc(r->type, result);				cgen(r, rg, r);			}		}		if(result != D_NONE) {			gmove(n->type, l->type, rg, r, lg, l);			gmove(n->type, nn->type, rg, r, result, nn);		} else			gmove(r->type, l->type, rg, r, lg, l);		regfree(lg);		regfree(rg);		break;	bitas:		n = l->left;		rg = regalloc(tfield, result);		if(l->complex >= r->complex) {			lg = regaddr(D_NONE);			lcgen(n, lg, Z);			lg |= I_INDIR;			cgen(r, rg, r);		} else {			cgen(r, rg, r);			lg = regaddr(D_NONE);			lcgen(n, lg, Z);			lg |= I_INDIR;		}		g = regalloc(n->type, D_NONE);		gmove(l->type, l->type, lg, l, g, l);		bitstore(l, rg, lg, g, result, nn);		break;	case OBIT:		if(result == D_NONE) {			nullwarn(l, Z);			break;		}		g = bitload(n, D_NONE, D_NONE, result, nn);		gopcode(OAS, nn->type, g, n, result, nn);		regfree(g);		break;	case ODOT:		sugen(l, D_TREE, nodrat, l->type->width);		if(result != D_NONE) {			warn(n, "non-interruptable temporary");			nod = *nodrat;			if(!r || r->op != OCONST) {				diag(n, "DOT and no offset");				break;			}			nod.xoffset += r->vconst;			nod.type = n->type;			cgen(&nod, result, nn);		}		break;	case OASLDIV:	case OASLMOD:	case OASDIV:	case OASMOD:		if(l->op == OBIT)			goto asbitop;		if(typefd[n->type->etype])			goto asbinop;		rg = D_TREE;		if(l->complex >= FNX || r->complex >= FNX) {			rg = D_TOS;			cgen(r, rg, r);			v = argoff;		} else		if(r->addable < INDEXED) {			rg = regalloc(n->type, D_NONE);			cgen(r, rg, r);		}		lg = D_TREE;		if(!simplv(l)) {			lg = regaddr(D_NONE);			lcgen(l, lg, Z);	/* destroys register optimization */			lg |= I_INDIR;		}		g = regpair(result);		gmove(l->type, n->type, lg, l, g, n);		if(rg == D_TOS)			adjsp(v - argoff);		gopcode(o, n->type, rg, r, g, n);		if(o == OASLMOD || o == OASMOD)			gmove(n->type, l->type, g+1, n, lg, l);		else			gmove(n->type, l->type, g, n, lg, l);		if(result != D_NONE)		if(o == OASLMOD || o == OASMOD)			gmove(n->type, nn->type, g+1, n, result, nn);		else			gmove(n->type, nn->type, g, n, result, nn);		regfree(g);		regfree(g+1);		regfree(lg);		regfree(rg);		break;	case OASXOR:	case OASAND:	case OASOR:		if(l->op == OBIT)			goto asbitop;		if(l->complex >= FNX ||		   l->addable < INDEXED ||		   result != D_NONE ||		   typefd[n->type->etype])			goto asbinop;		rg = D_TREE;		if(r->op != OCONST) {			rg = regalloc(n->type, D_NONE);			cgen(r, rg, r);		}		gopcode(o, l->type, rg, r, D_TREE, l);		regfree(rg);		break;	case OASADD:	case OASSUB:		if(l->op == OBIT ||		   l->complex >= FNX ||		   l->addable < INDEXED ||		   result != D_NONE ||		   typefd[n->type->etype])			goto asbinop;		v = vconst(r);		if(v > 0 && v <= 8) {			gopcode(o, n->type, D_TREE, r, D_TREE, l);			break;		}		rg = regalloc(n->type, D_NONE);		cgen(r, rg, r);		gopcode(o, n->type, rg, r, D_TREE, l);		regfree(rg);		break;	case OASLSHR:	case OASASHR:	case OASASHL:		if(l->op == OBIT ||		   l->complex >= FNX ||		   l->addable < INDEXED ||		   result != D_NONE ||		   typefd[n->type->etype])			goto asbinop;		rg = D_TREE;		v = vconst(r);		if(v <= 0 || v > 8) {			rg = regalloc(n->type, D_NONE);			cgen(r, rg, r);		}		lg = regalloc(n->type, D_NONE);		cgen(l, lg, l);		gopcode(o, n->type, rg, r, lg, l);		gmove(n->type, n->type, lg, l, D_TREE, l);		regfree(lg);		regfree(rg);		break;	case OASLMUL:	case OASMUL:	asbinop:		if(l->op == OBIT)			goto asbitop;		rg = D_TREE;		if(l->complex >= FNX || r->complex >= FNX) {			rg = D_TOS;			cgen(r, rg, r);			v = argoff;		} else		if(r->addable < INDEXED) {			rg = regalloc(n->type, D_NONE);			cgen(r, rg, r);		} else {			if(o == OASLSHR || o == OASASHR || o == OASASHL) {				v = vconst(r);				if(v <= 0 || v > 8) {					rg = regalloc(n->type, D_NONE);					cgen(r, rg, r);				}			}		}		lg = D_TREE;		if(!simplv(l)) {			lg = regaddr(D_NONE);			lcgen(l, lg, Z);	/* destroys register optimization */			lg |= I_INDIR;		}		g = regalloc(n->type, result);		gmove(l->type, n->type, lg, l, g, n);		if(rg == D_TOS)			adjsp(v - argoff);		if(o == OASXOR)			if(rg == D_TREE) {				rg = regalloc(n->type, D_NONE);				cgen(r, rg, r);			}		if(o == OASXOR || o == OASLSHR || o == OASASHR || o == OASASHL)			if(rg == D_TOS) {				rg = regalloc(n->type, D_NONE);				gmove(n->type, n->type, D_TOS, n, rg, n);			}		gopcode(o, n->type, rg, r, g, n);		gmove(n->type, l->type, g, n, lg, l);		if(result != D_NONE)			gmove(n->type, nn->type, g, n, result, nn);		regfree(g);		regfree(lg);		regfree(rg);		break;	asbitop:		rg = regaddr(D_NONE);		lg = regalloc(tfield, D_NONE);		if(l->complex >= r->complex) {			g = bitload(l, lg, rg, result, nn);			xg = regalloc(r->type, D_NONE);			cgen(r, xg, nn);		} else {			xg = regalloc(r->type, D_NONE);			cgen(r, xg, nn);			g = bitload(l, lg, rg, result, nn);		}		if(!typefd[n->type->etype]) {			if(o == OASLDIV || o == OASDIV) {				yg = regpair(result);				gmove(tfield, n->type, g, l, yg, n);				gopcode(o, n->type, xg, r, yg, n);				gmove(n->type, tfield, yg, n, g, l);				regfree(yg);				regfree(yg+1);				regfree(xg);				bitstore(l, g, rg, lg, D_NONE, nn);				break;			}			if(o == OASLMOD || o == OASMOD) {				yg = regpair(result);				gmove(tfield, n->type, g, l, yg, n);				gopcode(o, n->type, xg, r, yg, n);				gmove(n->type, tfield, yg+1, n, g, l);				regfree(yg);				regfree(yg+1);				regfree(xg);				bitstore(l, g, rg, lg, D_NONE, nn);				break;			}		}		yg = regalloc(n->type, result);		gmove(tfield, n->type, g, l, yg, n);		gopcode(o, n->type, xg, r, yg, n);		gmove(n->type, tfield, yg, n, g, l);		regfree(yg);		regfree(xg);		bitstore(l, g, rg, lg, D_NONE, nn);		break;	case OCAST:		if(result == D_NONE) {			nullwarn(l, Z);			break;		}		lg = result;		if(l->complex >= FNX)			lg = regret(l->type);		lg = eval(l, lg);		if(nocast(l->type, n->type)) {			gmove(n->type, nn->type, lg, l, result, nn);			regfree(lg);			break;		}		if(nocast(n->type, nn->type)) {			gmove(l->type, n->type, lg, l, result, nn);			regfree(lg);			break;		}		rg = regalloc(n->type, result);		gmove(l->type, n->type, lg, l, rg, n);		gmove(n->type, nn->type, rg, n, result, nn);		regfree(rg);		regfree(lg);		break;	case OCOND:		doinc(l, PRE);		boolgen(l, 1, D_NONE, Z, l);		p1 = p;		inargs++;		doinc(r->left, PRE);		cgen(r->left, result, nn);		doinc(r->left, POST);		gbranch(OGOTO);		patch(p1, pc);		p1 = p;		doinc(r->right, PRE);		cgen(r->right, result, nn);		doinc(r->right, POST);		patch(p1, pc);		inargs--;		break;	case OIND:		if(result == D_NONE) {			nullwarn(l, Z);			break;		}		lg = nodalloc(types[TIND], result, &nod);		nod.lineno = n->lineno;		if(l->op == OADD) {			if(l->left->op == OCONST) {				nod.xoffset += l->left->vconst;				l = l->right;			} else			if(l->right->op == OCONST) {				nod.xoffset += l->right->vconst;				l = l->left;			}		}		cgen(l, lg, l);		gmove(n->type, nn->type, D_TREE, &nod, result, nn);		regfree(lg);		break;	case OFUNC:		v = argoff;		inargs++;		gargs(r);		lg = D_TREE;		if(l->addable < INDEXED) {			lg = regaddr(result);			lcgen(l, lg, Z);			lg |= I_INDIR;		}		inargs--;		doinc(r, POST);		doinc(l, POST);		gopcode(OFUNC, types[TCHAR], D_NONE, Z, lg, l);		regfree(lg);		if(inargs)			adjsp(v - argoff);		if(result != D_NONE) {			lg = regret(n->type);			gmove(n->type, nn->type, lg, n, result, nn);		}		break;	case OLDIV:	case OLMOD:	case ODIV:	case OMOD:		if(result == D_NONE) {			nullwarn(l, r);			break;		}		if(typefd[n->type->etype])			goto binop;		if(r->addable >= INDEXED && r->complex < FNX) {			lg = regpair(result);			cgen(l, lg, l);			rg = D_TREE;		} else {			cgen(r, D_TOS, r);			v = argoff;			lg = regpair(result);			cgen(l, lg, l);			adjsp(v - argoff);			rg = D_TOS;		}		gopcode(o, n->type, rg, r, lg, l);		if(o == OMOD || o == OLMOD)			gmove(l->type, nn->type, lg+1, l, result, nn);		else			gmove(l->type, nn->type, lg, l, result, nn);		regfree(lg);		regfree(lg+1);		break;	case OMUL:	case OLMUL:		if(l->op == OCONST)			if(mulcon(r, l, result, nn))				break;		if(r->op == OCONST)			if(mulcon(l, r, result, nn))				break;		if(debug['M'])			print("%L multiply\n", n->lineno);		goto binop;	case OAND:		if(r->op == OCONST)		if(typeil[n->type->etype])		if(l->op == OCAST) {			if(typec[l->left->type->etype])			if(!(r->vconst & ~0xff)) {				l = l->left;				goto binop;			}			if(typeh[l->left->type->etype])			if(!(r->vconst & ~0xffff)) {				l = l->left;				goto binop;			}		}		goto binop;	case OADD:		if(result == D_TOS)		if(r->addable >= INDEXED)		if(l->op == OCONST)		if(typeil[l->type->etype]) {			v = l->vconst;			if(v > -32768 && v < 32768) {				rg = regaddr(D_NONE);				gmove(r->type, r->type, D_TREE, r, rg, r);				gopcode(OADDR, types[TSHORT], D_NONE, Z, rg, r);				p->to.offset = v;				p->to.type |= I_INDIR;				regfree(rg);				break;			}		}	case OSUB:		if(result == D_TOS)		if(l->addable >= INDEXED)		if(r->op == OCONST)		if(typeil[r->type->etype]) {			v = r->vconst;			if(v > -32768 && v < 32768) {				if(n->op == OSUB)					v = -v;				lg = regaddr(D_NONE);				gmove(l->type, l->type, D_TREE, l, lg, l);				gopcode(OADDR, types[TSHORT], D_NONE, Z, lg, l);				p->to.offset = v;				p->to.type |= I_INDIR;				regfree(lg);				break;			}		}		goto binop;	case OOR:	case OXOR:	binop:		if(result == D_NONE) {			nullwarn(l, r);			break;		}		if(l->complex >= FNX && r->complex >= FNX) {			cgen(r, D_TOS, r);			v = argoff;			lg = regalloc(l->type, result);			cgen(l, lg, l);			adjsp(v - argoff);			if(o == OXOR) {				rg = regalloc(r->type, D_NONE);				gmove(r->type, r->type, D_TOS, r, rg, r);				gopcode(o, n->type, rg, r, lg, l);				regfree(rg);			} else				gopcode(o, n->type, D_TOS, r, lg, l);			gmove(n->type, nn->type, lg, l, result, nn);			regfree(lg);			break;		}		if(l->complex >= r->complex) {			if(l->op == OADDR && (o == OADD || o == OSUB))				lg = regaddr(result);			else				lg = regalloc(l->type, result);			cgen(l, lg, l);			rg = eval(r, D_NONE);		} else {			rg = regalloc(r->type, D_NONE);			cgen(r, rg, r);			lg = regalloc(l->type, result);			cgen(l, lg, l);		}		if(o == OXOR) {			if(rg == D_TREE) {				rg = regalloc(r->type, D_NONE);				cgen(r, rg, r);			}			if(rg == D_TOS) {				rg = regalloc(r->type, D_NONE);				gmove(r->type, r->type, D_TOS, r, rg, r);			}		}		gopcode(o, n->type, rg, r, lg, l);		gmove(n->type, nn->type, lg, l, result, nn);		regfree(lg);		regfree(rg);		break;	case OASHL:		if(r->op == OCONST)			if(shlcon(l, r, result, nn))				break;	case OLSHR:	case OASHR:		if(result == D_NONE) {			nullwarn(l, r);			break;		}		if(l->complex >= FNX && r->complex >= FNX) {			cgen(r, D_TOS, r);			v = argoff;			lg = regalloc(l->type, result);			cgen(l, lg, l);			adjsp(v - argoff);			rg = regalloc(r->type, D_NONE);			gopcode(OAS, r->type, D_TOS, r, rg, r);			gopcode(n->op, n->type, rg, r, lg, l);			gmove(n->type, nn->type, lg, l, result, nn);			regfree(lg);			regfree(rg);			break;		}		if(l->complex >= r->complex) {			lg = regalloc(l->type, result);			cgen(l, lg, l);			v = vconst(r);			if(v <= 0 || v > 8) {				rg = regalloc(r->type, D_NONE);				cgen(r, rg, r);			} else				rg = eval(r, D_NONE);		} else {			rg = regalloc(r->type, D_NONE);			cgen(r, rg, r);			lg = regalloc(l->type, result);			cgen(l, lg, l);		}		gopcode(o, n->type, rg, r, lg, l);		gmove(n->type, nn->type, lg, l, result, nn);		regfree(lg);		regfree(rg);		break;	case ONEG:	case OCOM:		if(result == D_NONE) {			nullwarn(l, Z);			break;		}		lg = regalloc(l->type, result);		cgen(l, lg, l);		gopcode(o, l->type, D_NONE, Z, lg, l);		gmove(n->type, nn->type, lg, l, result, nn);		regfree(lg);		break;	case OADDR:		if(result == D_NONE) {			nullwarn(l, Z);			break;		}		lcgen(l, result, nn);		break;	case OEQ:	case ONE:	case OLE:	case OLT:	case OGE:	case OGT:	case OLO:	case OLS:	case OHI:	case OHS:		if(result == D_NONE) {			nullwarn(l, r);			break;		}		boolgen(n, 1, result, nn, Z);

⌨️ 快捷键说明

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