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

📄 com.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
		if(tcompat(n, T, l->type, tindir))			goto bad;		n->type = l->type->link;		n->addable = 1;		break;	case OSTRUCT:		if(tcomx(n))			goto bad;		break;	}	t = n->type;	if(t == T)		goto bad;	if(t->width < 0) {		snap(t);		if(t->width < 0) {			if(typesu[t->etype] && t->tag)				diag(n, "structure not fully declared %s", t->tag->name);			else				diag(n, "structure not fully declared");			goto bad;		}	}	if(typeaf[t->etype]) {		if(f & ADDROF)			goto addaddr;		if(f & ADDROP)			warn(n, "address of array/func ignored");	}	return 0;addaddr:	if(tlvalue(n))		goto bad;	l = new1(OXXX, Z, Z);	*l = *n;	n->op = OADDR;	if(l->type->etype == TARRAY)		l->type = l->type->link;	n->left = l;	n->right = Z;	n->addable = 0;	n->type = typ(TIND, l->type);	n->type->width = types[TIND]->width;	return 0;bad:	n->type = T;	return 1;}inttcoma(Node *l, Node *n, Type *t, int f){	Node *n1;	int o;	if(t != T)	if(t->etype == TOLD || t->etype == TDOT)	/* .../old in prototype */		t = T;	if(n == Z) {		if(t != T && !sametype(t, types[TVOID])) {			diag(n, "not enough function arguments: %F", l);			return 1;		}		return 0;	}	if(n->op == OLIST) {		o = tcoma(l, n->left, t, 0);		if(t != T) {			t = t->down;			if(t == T)				t = types[TVOID];		}		return o | tcoma(l, n->right, t, 1);	}	if(f && t != T)		tcoma(l, Z, t->down, 0);	if(tcom(n) || tcompat(n, T, n->type, targ))		return 1;	if(sametype(t, types[TVOID])) {		diag(n, "too many function arguments: %F", l);		return 1;	}	if(t != T) {		typeext(t, n);		if(stcompat(nodproto, t, n->type, tasign)) {			diag(l, "argument prototype mismatch \"%T\" for \"%T\": %F",				n->type, t, l);			return 1;		}		switch(t->etype) {		case TCHAR:		case TSHORT:			t = types[TINT];			break;		case TUCHAR:		case TUSHORT:			t = types[TUINT];			break;		}	} else	switch(n->type->etype)	{	case TCHAR:	case TSHORT:		t = types[TINT];		break;	case TUCHAR:	case TUSHORT:		t = types[TUINT];		break;	case TFLOAT:		t = types[TDOUBLE];	}	if(t != T && !sametype(t, n->type)) {		n1 = new1(OXXX, Z, Z);		*n1 = *n;		n->op = OCAST;		n->left = n1;		n->right = Z;		n->type = t;		n->addable = 0;	}	return 0;}inttcomd(Node *n){	Type *t;	long o;	o = 0;	t = dotsearch(n->sym, n->left->type->link, n, &o);	if(t == T) {		diag(n, "not a member of struct/union: %F", n);		return 1;	}	makedot(n, t, o);	return 0;}inttcomx(Node *n){	Type *t;	Node *l, *r, **ar, **al;	int e;	e = 0;	if(n->type->etype != TSTRUCT) {		diag(n, "constructor must be a structure");		return 1;	}	l = invert(n->left);	n->left = l;	al = &n->left;	for(t = n->type->link; t != T; t = t->down) {		if(l == Z) {			diag(n, "constructor list too short");			return 1;		}		if(l->op == OLIST) {			r = l->left;			ar = &l->left;			al = &l->right;			l = l->right;		} else {			r = l;			ar = al;			l = Z;		}		if(tcom(r))			e++;		typeext(t, r);		if(tcompat(n, t, r->type, tasign))			e++;		constas(n, t, r->type);		if(!e && !sametype(t, r->type)) {			r = new1(OCAST, r, Z);			r->type = t;			*ar = r;		}	}	if(l != Z) {		diag(n, "constructor list too long");		return 1;	}	return e;}inttlvalue(Node *n){	if(!n->addable) {		diag(n, "not an l-value");		return 1;	}	return 0;}/* *	general rewrite *	(IND(ADDR x)) ==> x *	(ADDR(IND x)) ==> x *	remove some zero operands *	remove no op casts *	evaluate constants */voidccom(Node *n){	Node *l, *r;	int t;loop:	if(n == Z)		return;	l = n->left;	r = n->right;	switch(n->op) {	case OAS:	case OASXOR:	case OASAND:	case OASOR:	case OASMOD:	case OASLMOD:	case OASLSHR:	case OASASHR:	case OASASHL:	case OASDIV:	case OASLDIV:	case OASMUL:	case OASLMUL:	case OASSUB:	case OASADD:		ccom(l);		ccom(r);		if(n->op == OASLSHR || n->op == OASASHR || n->op == OASASHL)		if(r->op == OCONST) {			t = n->type->width * 8;	/* bits per byte */			if(r->vconst >= t || r->vconst < 0)				warn(n, "stupid shift: %lld", r->vconst);		}		break;	case OCAST:		ccom(l);		if(l->op == OCONST) {			evconst(n);			if(n->op == OCONST)				break;		}		if(nocast(l->type, n->type)) {			l->type = n->type;			*n = *l;		}		break;	case OCOND:		ccom(l);		ccom(r);		if(l->op == OCONST)			if(vconst(l) == 0)				*n = *r->right;			else				*n = *r->left;		break;	case OREGISTER:	case OINDREG:	case OCONST:	case ONAME:		break;	case OADDR:		ccom(l);		l->etype = TVOID;		if(l->op == OIND) {			l->left->type = n->type;			*n = *l->left;			break;		}		goto common;	case OIND:		ccom(l);		if(l->op == OADDR) {			l->left->type = n->type;			*n = *l->left;			break;		}		goto common;	case OEQ:	case ONE:	case OLE:	case OGE:	case OLT:	case OGT:	case OLS:	case OHS:	case OLO:	case OHI:		ccom(l);		ccom(r);		if(compar(n, 0) || compar(n, 1))			break;		relcon(l, r);		relcon(r, l);		goto common;	case OASHR:	case OASHL:	case OLSHR:		ccom(l);		if(vconst(l) == 0 && !side(r)) {			*n = *l;			break;		}		ccom(r);		if(vconst(r) == 0) {			*n = *l;			break;		}		if(r->op == OCONST) {			t = n->type->width * 8;	/* bits per byte */			if(r->vconst >= t || r->vconst <= -t)				warn(n, "stupid shift: %lld", r->vconst);		}		goto common;	case OMUL:	case OLMUL:		ccom(l);		t = vconst(l);		if(t == 0 && !side(r)) {			*n = *l;			break;		}		if(t == 1) {			*n = *r;			goto loop;		}		ccom(r);		t = vconst(r);		if(t == 0 && !side(l)) {			*n = *r;			break;		}		if(t == 1) {			*n = *l;			break;		}		goto common;	case ODIV:	case OLDIV:		ccom(l);		if(vconst(l) == 0 && !side(r)) {			*n = *l;			break;		}		ccom(r);		t = vconst(r);		if(t == 0) {			diag(n, "divide check");			*n = *r;			break;		}		if(t == 1) {			*n = *l;			break;		}		goto common;	case OSUB:		ccom(r);		if(r->op == OCONST) {			if(typefd[r->type->etype]) {				n->op = OADD;				r->fconst = -r->fconst;				goto loop;			} else {				n->op = OADD;				r->vconst = -r->vconst;				goto loop;			}		}		ccom(l);		goto common;	case OXOR:	case OOR:	case OADD:		ccom(l);		if(vconst(l) == 0) {			*n = *r;			goto loop;		}		ccom(r);		if(vconst(r) == 0) {			*n = *l;			break;		}		goto commute;	case OAND:		ccom(l);		ccom(r);		if(vconst(l) == 0 && !side(r)) {			*n = *l;			break;		}		if(vconst(r) == 0 && !side(l)) {			*n = *r;			break;		}	commute:		/* look for commutative constant */		if(r->op == OCONST) {			if(l->op == n->op) {				if(l->left->op == OCONST) {					n->right = l->right;					l->right = r;					goto loop;				}				if(l->right->op == OCONST) {					n->right = l->left;					l->left = r;					goto loop;				}			}		}		if(l->op == OCONST) {			if(r->op == n->op) {				if(r->left->op == OCONST) {					n->left = r->right;					r->right = l;					goto loop;				}				if(r->right->op == OCONST) {					n->left = r->left;					r->left = l;					goto loop;				}			}		}		goto common;	case OANDAND:		ccom(l);		if(vconst(l) == 0) {			*n = *l;			break;		}		ccom(r);		goto common;	case OOROR:		ccom(l);		if(l->op == OCONST && l->vconst != 0) {			*n = *l;			n->vconst = 1;			break;		}		ccom(r);		goto common;	default:		if(l != Z)			ccom(l);		if(r != Z)			ccom(r);	common:		if(l != Z)		if(l->op != OCONST)			break;		if(r != Z)		if(r->op != OCONST)			break;		evconst(n);	}}/*	OEQ, ONE, OLE, OLS, OLT, OLO, OGE, OHS, OGT, OHI */static char *cmps[12] = {	"==", "!=", "<=", "<=", "<", "<", ">=", ">=", ">", ">",};/* 128-bit numbers */typedef struct Big Big;struct Big{	vlong a;	uvlong b;};static intcmp(Big x, Big y){	if(x.a != y.a){		if(x.a < y.a)			return -1;		return 1;	}	if(x.b != y.b){		if(x.b < y.b)			return -1;		return 1;	}	return 0;}static Bigadd(Big x, int y){	uvlong ob;		ob = x.b;	x.b += y;	if(y > 0 && x.b < ob)		x.a++;	if(y < 0 && x.b > ob)		x.a--;	return x;} Bigbig(vlong a, uvlong b){	Big x;	x.a = a;	x.b = b;	return x;}intcompar(Node *n, int reverse){	Big lo, hi, x;	int op;	char xbuf[40], cmpbuf[50];	Node *l, *r;	Type *lt, *rt;	/*	 * The point of this function is to diagnose comparisons 	 * that can never be true or that look misleading because	 * of the `usual arithmetic conversions'.  As an example 	 * of the latter, if x is a ulong, then if(x <= -1) really means	 * if(x <= 0xFFFFFFFF), while if(x <= -1LL) really means	 * what it says (but 8c compiles it wrong anyway).	 */	if(reverse){		r = n->left;		l = n->right;		op = comrel[relindex(n->op)];	}else{		l = n->left;		r = n->right;		op = n->op;	}	/*	 * Skip over left casts to find out the original expression range.	 */	while(l->op == OCAST)		l = l->left;	if(l->op == OCONST)		return 0;	lt = l->type;	if(l->op == ONAME){		lt = l->sym->type;		if(lt && lt->etype == TARRAY)			lt = lt->link;	}	if(lt == T)		return 0;	if(lt->etype == TXXX || lt->etype > TUVLONG)		return 0;		/*	 * Skip over the right casts to find the on-screen value.	 */	if(r->op != OCONST)		return 0;	while(r->oldop == OCAST && !r->xcast)		r = r->left;	rt = r->type;	if(rt == T)		return 0;	x.b = r->vconst;	x.a = 0;	if((rt->etype&1) && r->vconst < 0)	/* signed negative */		x.a = ~0ULL;	if((lt->etype&1)==0){		/* unsigned */		lo = big(0, 0);		if(lt->width == 8)			hi = big(0, ~0ULL);		else			hi = big(0, (1LL<<(l->type->width*8))-1);	}else{		lo = big(~0ULL, -(1LL<<(l->type->width*8-1)));		hi = big(0, (1LL<<(l->type->width*8-1))-1);	}	switch(op){	case OLT:	case OLO:	case OGE:	case OHS:		if(cmp(x, lo) <= 0)			goto useless;		if(cmp(x, add(hi, 1)) >= 0)			goto useless;		break;	case OLE:	case OLS:	case OGT:	case OHI:		if(cmp(x, add(lo, -1)) <= 0)			goto useless;		if(cmp(x, hi) >= 0)			goto useless;		break;	case OEQ:	case ONE:		/*		 * Don't warn about comparisons if the expression		 * is as wide as the value: the compiler-supplied casts		 * will make both outcomes possible.		 */		if(lt->width >= rt->width && debug['w'] < 2)			return 0;		if(cmp(x, lo) < 0 || cmp(x, hi) > 0)			goto useless;		break;	}	return 0;useless:	if((x.a==0 && x.b<=9) || (x.a==~0LL && x.b >= -9ULL))		snprint(xbuf, sizeof xbuf, "%lld", x.b);	else if(x.a == 0)		snprint(xbuf, sizeof xbuf, "%#llux", x.b);	else		snprint(xbuf, sizeof xbuf, "%#llx", x.b);	if(reverse)		snprint(cmpbuf, sizeof cmpbuf, "%s %s %T",			xbuf, cmps[relindex(n->op)], lt);	else		snprint(cmpbuf, sizeof cmpbuf, "%T %s %s",			lt, cmps[relindex(n->op)], xbuf);	warn(n, "useless or misleading comparison: %s", cmpbuf);	return 0;}

⌨️ 快捷键说明

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