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

📄 scon.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include "cc.h"static Node*acast(Type *t, Node *n){	if(n->type->etype != t->etype || n->op == OBIT) {		n = new1(OCAST, n, Z);		if(nocast(n->left->type, t))			*n = *n->left;		n->type = t;	}	return n;}voidevconst(Node *n){	Node *l, *r;	int et, isf;	vlong v;	double d;	if(n == Z || n->type == T)		return;	et = n->type->etype;	isf = typefd[et];	l = n->left;	r = n->right;	d = 0;	v = 0;	switch(n->op) {	default:		return;	case ONEG:		if(isf)			d = -l->fconst;		else			v = -l->vconst;		break;	case OCOM:		v = ~l->vconst;		break;	case OCAST:		if(et == TVOID)			return;		et = l->type->etype;		if(isf) {			if(typefd[et])				d = l->fconst;			else				d = l->vconst;		} else {			if(typefd[et])				v = l->fconst;			else				v = convvtox(l->vconst, n->type->etype);		}		break;	case OCONST:		break;	case OADD:		if(isf)			d = l->fconst + r->fconst;		else {			v = l->vconst + r->vconst;		}		break;	case OSUB:		if(isf)			d = l->fconst - r->fconst;		else			v = l->vconst - r->vconst;		break;	case OMUL:		if(isf)			d = l->fconst * r->fconst;		else {			v = l->vconst * r->vconst;		}		break;	case OLMUL:		v = (uvlong)l->vconst * (uvlong)r->vconst;		break;	case ODIV:		if(vconst(r) == 0) {			warn(n, "divide by zero");			return;		}		if(isf)			d = l->fconst / r->fconst;		else			v = l->vconst / r->vconst;		break;	case OLDIV:		if(vconst(r) == 0) {			warn(n, "divide by zero");			return;		}		v = (uvlong)l->vconst / (uvlong)r->vconst;		break;	case OMOD:		if(vconst(r) == 0) {			warn(n, "modulo by zero");			return;		}		v = l->vconst % r->vconst;		break;	case OLMOD:		if(vconst(r) == 0) {			warn(n, "modulo by zero");			return;		}		v = (uvlong)l->vconst % (uvlong)r->vconst;		break;	case OAND:		v = l->vconst & r->vconst;		break;	case OOR:		v = l->vconst | r->vconst;		break;	case OXOR:		v = l->vconst ^ r->vconst;		break;	case OLSHR:		v = (uvlong)l->vconst >> r->vconst;		break;	case OASHR:		v = l->vconst >> r->vconst;		break;	case OASHL:		v = l->vconst << r->vconst;		break;	case OLO:		v = (uvlong)l->vconst < (uvlong)r->vconst;		break;	case OLT:		if(typefd[l->type->etype])			v = l->fconst < r->fconst;		else			v = l->vconst < r->vconst;		break;	case OHI:		v = (uvlong)l->vconst > (uvlong)r->vconst;		break;	case OGT:		if(typefd[l->type->etype])			v = l->fconst > r->fconst;		else			v = l->vconst > r->vconst;		break;	case OLS:		v = (uvlong)l->vconst <= (uvlong)r->vconst;		break;	case OLE:		if(typefd[l->type->etype])			v = l->fconst <= r->fconst;		else			v = l->vconst <= r->vconst;		break;	case OHS:		v = (uvlong)l->vconst >= (uvlong)r->vconst;		break;	case OGE:		if(typefd[l->type->etype])			v = l->fconst >= r->fconst;		else			v = l->vconst >= r->vconst;		break;	case OEQ:		if(typefd[l->type->etype])			v = l->fconst == r->fconst;		else			v = l->vconst == r->vconst;		break;	case ONE:		if(typefd[l->type->etype])			v = l->fconst != r->fconst;		else			v = l->vconst != r->vconst;		break;	case ONOT:		if(typefd[l->type->etype])			v = !l->fconst;		else			v = !l->vconst;		break;	case OANDAND:		if(typefd[l->type->etype])			v = l->fconst && r->fconst;		else			v = l->vconst && r->vconst;		break;	case OOROR:		if(typefd[l->type->etype])			v = l->fconst || r->fconst;		else			v = l->vconst || r->vconst;		break;	}	if(isf) {		n->fconst = d;	} else {		n->vconst = convvtox(v, n->type->etype);	}	n->oldop = n->op;	n->op = OCONST;}voidacom(Node *n){	Type *t;	Node *l, *r;	int i;	switch(n->op)	{	case ONAME:	case OCONST:	case OSTRING:	case OINDREG:	case OREGISTER:		return;	case ONEG:		l = n->left;		if(addo(n) && addo(l))			break;		acom(l);		return;	case OADD:	case OSUB:	case OMUL:		l = n->left;		r = n->right;		if(addo(n)) {			if(addo(r))				break;			if(addo(l))				break;		}		acom(l);		acom(r);		return;	default:		l = n->left;		r = n->right;		if(l != Z)			acom(l);		if(r != Z)			acom(r);		return;	}	/* bust terms out */	t = n->type;	term[0].mult = 0;	term[0].node = Z;	nterm = 1;	acom1(1, n);	if(debug['m'])	for(i=0; i<nterm; i++) {		print("%d %3lld ", i, term[i].mult);		prtree1(term[i].node, 1, 0);	}	if(nterm < NTERM)		acom2(n, t);	n->type = t;}intacomcmp1(const void *a1, const void *a2){	vlong c1, c2;	Term *t1, *t2;	t1 = (Term*)a1;	t2 = (Term*)a2;	c1 = t1->mult;	if(c1 < 0)		c1 = -c1;	c2 = t2->mult;	if(c2 < 0)		c2 = -c2;	if(c1 > c2)		return 1;	if(c1 < c2)		return -1;	c1 = 1;	if(t1->mult < 0)		c1 = 0;	c2 = 1;	if(t2->mult < 0)		c2 = 0;	if(c2 -= c1)		return c2;	if(t2 > t1)		return 1;	return -1;}intacomcmp2(const void *a1, const void *a2){	vlong c1, c2;	Term *t1, *t2;	t1 = (Term*)a1;	t2 = (Term*)a2;	c1 = t1->mult;	c2 = t2->mult;	if(c1 > c2)		return 1;	if(c1 < c2)		return -1;	if(t2 > t1)		return 1;	return -1;}voidacom2(Node *n, Type *t){	Node *l, *r;	Term trm[NTERM];	int et, nt, i, j;	vlong c1, c2;	/*	 * copy into automatic	 */	c2 = 0;	nt = nterm;	for(i=0; i<nt; i++)		trm[i] = term[i];	/*	 * recur on subtrees	 */	j = 0;	for(i=1; i<nt; i++) {		c1 = trm[i].mult;		if(c1 == 0)			continue;		l = trm[i].node;		if(l != Z) {			j = 1;			acom(l);		}	}	c1 = trm[0].mult;	if(j == 0) {		n->oldop = n->op;		n->op = OCONST;		n->vconst = c1;		return;	}	et = t->etype;	/*	 * prepare constant term,	 * combine it with an addressing term	 */	if(c1 != 0) {		l = new1(OCONST, Z, Z);		l->type = t;		l->vconst = c1;		trm[0].mult = 1;		for(i=1; i<nt; i++) {			if(trm[i].mult != 1)				continue;			r = trm[i].node;			if(r->op != OADDR)				continue;			r->type = t;			l = new1(OADD, r, l);			l->type = t;			trm[i].mult = 0;			break;		}		trm[0].node = l;	}	/*	 * look for factorable terms	 * c1*i + c1*c2*j -> c1*(i + c2*j)	 */	qsort(trm+1, nt-1, sizeof(trm[0]), acomcmp1);	for(i=nt-1; i>=0; i--) {		c1 = trm[i].mult;		if(c1 < 0)			c1 = -c1;		if(c1 <= 1)			continue;		for(j=i+1; j<nt; j++) {			c2 = trm[j].mult;			if(c2 < 0)				c2 = -c2;			if(c2 <= 1)				continue;			if(c2 % c1)				continue;			r = trm[j].node;			if(r->type->etype != et)				r = acast(t, r);			c2 = trm[j].mult/trm[i].mult;			if(c2 != 1 && c2 != -1) {				r = new1(OMUL, r, new(OCONST, Z, Z));				r->type = t;				r->right->type = t;				r->right->vconst = c2;			}			l = trm[i].node;			if(l->type->etype != et)				l = acast(t, l);			r = new1(OADD, l, r);			r->type = t;			if(c2 == -1)				r->op = OSUB;			trm[i].node = r;			trm[j].mult = 0;		}	}	if(debug['m']) {		print("\n");		for(i=0; i<nt; i++) {			print("%d %3lld ", i, trm[i].mult);			prtree1(trm[i].node, 1, 0);		}	}	/*	 * put it all back together	 */	qsort(trm+1, nt-1, sizeof(trm[0]), acomcmp2);	l = Z;	for(i=nt-1; i>=0; i--) {		c1 = trm[i].mult;		if(c1 == 0)			continue;		r = trm[i].node;		if(r->type->etype != et || r->op == OBIT)			r = acast(t, r);		if(c1 != 1 && c1 != -1) {			r = new1(OMUL, r, new(OCONST, Z, Z));			r->type = t;			r->right->type = t;			if(c1 < 0) {				r->right->vconst = -c1;				c1 = -1;			} else {				r->right->vconst = c1;				c1 = 1;			}		}		if(l == Z) {			l = r;			c2 = c1;			continue;		}		if(c1 < 0)			if(c2 < 0)				l = new1(OADD, l, r);			else				l = new1(OSUB, l, r);		else			if(c2 < 0) {				l = new1(OSUB, r, l);				c2 = 1;			} else				l = new1(OADD, l, r);		l->type = t;	}	if(c2 < 0) {		r = new1(OCONST, 0, 0);		r->vconst = 0;		r->type = t;		l = new1(OSUB, r, l);		l->type = t;	}	*n = *l;}voidacom1(vlong v, Node *n){	Node *l, *r;	if(v == 0 || nterm >= NTERM)		return;	if(!addo(n)) {		if(n->op == OCONST)		if(!typefd[n->type->etype]) {			term[0].mult += v*n->vconst;			return;		}		term[nterm].mult = v;		term[nterm].node = n;		nterm++;		return;	}	switch(n->op) {	case OCAST:		acom1(v, n->left);		break;	case ONEG:		acom1(-v, n->left);		break;	case OADD:		acom1(v, n->left);		acom1(v, n->right);		break;	case OSUB:		acom1(v, n->left);		acom1(-v, n->right);		break;	case OMUL:		l = n->left;		r = n->right;		if(l->op == OCONST)		if(!typefd[n->type->etype]) {			acom1(v*l->vconst, r);			break;		}		if(r->op == OCONST)		if(!typefd[n->type->etype]) {			acom1(v*r->vconst, l);			break;		}		break;	default:		diag(n, "not addo");	}}intaddo(Node *n){	if(n != Z)	if(!typefd[n->type->etype])	if(!typev[n->type->etype] || ewidth[TVLONG] == ewidth[TIND])	switch(n->op) {	case OCAST:		if(nilcast(n->left->type, n->type))			return 1;		break;	case ONEG:	case OADD:	case OSUB:		return 1;	case OMUL:		if(n->left->op == OCONST)			return 1;		if(n->right->op == OCONST)			return 1;	}	return 0;}

⌨️ 快捷键说明

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