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

📄 pgen.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include "gc.h"voidcodgen(Node *n, Node *nn){	Prog *sp;	Node *n1, nod, nod1;	cursafe = 0;	curarg = 0;	maxargsafe = 0;	/*	 * isolate name	 */	for(n1 = nn;; n1 = n1->left) {		if(n1 == Z) {			diag(nn, "cant find function name");			return;		}		if(n1->op == ONAME)			break;	}	nearln = nn->lineno;	gpseudo(ATEXT, n1->sym, nodconst(stkoff));	sp = p;	/*	 * isolate first argument	 */	if(REGARG >= 0) {			if(typecmplx[thisfn->link->etype]) {			nod1 = *nodret->left;			nodreg(&nod, &nod1, REGARG);			gmove(&nod, &nod1);		} else		if(firstarg && typeword[firstargtype->etype]) {			nod1 = *nodret->left;			nod1.sym = firstarg;			nod1.type = firstargtype;			nod1.xoffset = align(0, firstargtype, Aarg1);			nod1.etype = firstargtype->etype;			nodreg(&nod, &nod1, REGARG);			gmove(&nod, &nod1);		}	}	canreach = 1;	warnreach = 1;	gen(n);	if(canreach && thisfn->link->etype != TVOID)		warn(Z, "no return at end of function: %s", n1->sym->name);	noretval(3);	gbranch(ORETURN);	if(!debug['N'] || debug['R'] || debug['P'])		regopt(sp);		if(thechar=='6' || thechar=='7')	/* [sic] */		maxargsafe = round(maxargsafe, 8);	sp->to.offset += maxargsafe;}voidsupgen(Node *n){	int owarn;	long spc;	Prog *sp;	if(n == Z)		return;	suppress++;	owarn = warnreach;	warnreach = 0;	spc = pc;	sp = lastp;	gen(n);	lastp = sp;	pc = spc;	sp->link = nil;	suppress--;	warnreach = owarn;}voidgen(Node *n){	Node *l, nod;	Prog *sp, *spc, *spb;	Case *cn;	long sbc, scc;	int snbreak, sncontin;	int f, o, oldreach;loop:	if(n == Z)		return;	nearln = n->lineno;	o = n->op;	if(debug['G'])		if(o != OLIST)			print("%L %O\n", nearln, o);	if(!canreach) {		switch(o) {		case OLABEL:		case OCASE:		case OLIST:		case OBREAK:		case OFOR:		case OWHILE:		case ODWHILE:			/* all handled specially - see switch body below */			break;		default:			if(warnreach) {				warn(n, "unreachable code %O", o);				warnreach = 0;			}		}	}	switch(o) {	default:		complex(n);		cgen(n, Z);		break;	case OLIST:		gen(n->left);	rloop:		n = n->right;		goto loop;	case ORETURN:		canreach = 0;		warnreach = !suppress;		complex(n);		if(n->type == T)			break;		l = n->left;		if(l == Z) {			noretval(3);			gbranch(ORETURN);			break;		}		if(typecmplx[n->type->etype]) {			sugen(l, nodret, n->type->width);			noretval(3);			gbranch(ORETURN);			break;		}		regret(&nod, n);		cgen(l, &nod);		regfree(&nod);		if(typefd[n->type->etype])			noretval(1);		else			noretval(2);		gbranch(ORETURN);		break;	case OLABEL:		canreach = 1;		l = n->left;		if(l) {			l->pc = pc;			if(l->label)				patch(l->label, pc);		}		gbranch(OGOTO);	/* prevent self reference in reg */		patch(p, pc);		goto rloop;	case OGOTO:		canreach = 0;		warnreach = !suppress;		n = n->left;		if(n == Z)			return;		if(n->complex == 0) {			diag(Z, "label undefined: %s", n->sym->name);			return;		}		if(suppress)			return;		gbranch(OGOTO);		if(n->pc) {			patch(p, n->pc);			return;		}		if(n->label)			patch(n->label, pc-1);		n->label = p;		return;	case OCASE:		canreach = 1;		l = n->left;		if(cases == C)			diag(n, "case/default outside a switch");		if(l == Z) {			cas();			cases->val = 0;			cases->def = 1;			cases->label = pc;			goto rloop;		}		complex(l);		if(l->type == T)			goto rloop;		if(l->op == OCONST)		if(typeword[l->type->etype] && l->type->etype != TIND) {			cas();			cases->val = l->vconst;			cases->def = 0;			cases->label = pc;			cases->isv = typev[l->type->etype];			goto rloop;		}		diag(n, "case expression must be integer constant");		goto rloop;	case OSWITCH:		l = n->left;		complex(l);		if(l->type == T)			break;		if(!typeword[l->type->etype] || l->type->etype == TIND) {			diag(n, "switch expression must be integer");			break;		}		gbranch(OGOTO);		/* entry */		sp = p;		cn = cases;		cases = C;		cas();		sbc = breakpc;		breakpc = pc;		snbreak = nbreak;		nbreak = 0;		gbranch(OGOTO);		spb = p;		gen(n->right);		/* body */		if(canreach){			gbranch(OGOTO);			patch(p, breakpc);			nbreak++;		}		patch(sp, pc);		regalloc(&nod, l, Z);		/* always signed */		if(typev[l->type->etype])			nod.type = types[TVLONG];		else			nod.type = types[TLONG];		cgen(l, &nod);		doswit(&nod);		regfree(&nod);		patch(spb, pc);		cases = cn;		breakpc = sbc;		canreach = nbreak!=0;		if(canreach == 0)			warnreach = !suppress;		nbreak = snbreak;		break;	case OWHILE:	case ODWHILE:		l = n->left;		gbranch(OGOTO);		/* entry */		sp = p;		scc = continpc;		continpc = pc;		gbranch(OGOTO);		spc = p;		sbc = breakpc;		breakpc = pc;		snbreak = nbreak;		nbreak = 0;		gbranch(OGOTO);		spb = p;		patch(spc, pc);		if(n->op == OWHILE)			patch(sp, pc);		bcomplex(l, Z);		/* test */		patch(p, breakpc);		if(l->op != OCONST || vconst(l) == 0)			nbreak++;		if(n->op == ODWHILE)			patch(sp, pc);		gen(n->right);		/* body */		gbranch(OGOTO);		patch(p, continpc);		patch(spb, pc);		continpc = scc;		breakpc = sbc;		canreach = nbreak!=0;		if(canreach == 0)			warnreach = !suppress;		nbreak = snbreak;		break;	case OFOR:		l = n->left;		if(!canreach && l->right->left && warnreach) {			warn(n, "unreachable code FOR");			warnreach = 0;		}		gen(l->right->left);	/* init */		gbranch(OGOTO);		/* entry */		sp = p;		/* 		 * if there are no incoming labels in the 		 * body and the top's not reachable, warn		 */		if(!canreach && warnreach && deadheads(n)) {			warn(n, "unreachable code %O", o);			warnreach = 0;		}		scc = continpc;		continpc = pc;		gbranch(OGOTO);		spc = p;		sbc = breakpc;		breakpc = pc;		snbreak = nbreak;		nbreak = 0;		sncontin = ncontin;		ncontin = 0;		gbranch(OGOTO);		spb = p;		patch(spc, pc);		gen(l->right->right);	/* inc */		patch(sp, pc);			if(l->left != Z) {	/* test */			bcomplex(l->left, Z);			patch(p, breakpc);			if(l->left->op != OCONST || vconst(l->left) == 0)				nbreak++;		}		canreach = 1;		gen(n->right);		/* body */		if(canreach){			gbranch(OGOTO);			patch(p, continpc);			ncontin++;		}		if(!ncontin && l->right->right && warnreach) {			warn(l->right->right, "unreachable FOR inc");			warnreach = 0;		}		patch(spb, pc);		continpc = scc;		breakpc = sbc;		canreach = nbreak!=0;		if(canreach == 0)			warnreach = !suppress;		nbreak = snbreak;		ncontin = sncontin;		break;	case OCONTINUE:		if(continpc < 0) {			diag(n, "continue not in a loop");			break;		}		gbranch(OGOTO);		patch(p, continpc);		ncontin++;		canreach = 0;		warnreach = !suppress;		break;	case OBREAK:		if(breakpc < 0) {			diag(n, "break not in a loop");			break;		}		/*		 * Don't complain about unreachable break statements.		 * There are breaks hidden in yacc's output and some people		 * write return; break; in their switch statements out of habit.		 * However, don't confuse the analysis by inserting an 		 * unreachable reference to breakpc either.		 */		if(!canreach)			break;		gbranch(OGOTO);		patch(p, breakpc);		nbreak++;		canreach = 0;		warnreach = !suppress;		break;	case OIF:		l = n->left;		if(bcomplex(l, n->right)) {			if(typefd[l->type->etype])				f = !l->fconst;			else				f = !l->vconst;			if(debug['c'])				print("%L const if %s\n", nearln, f ? "false" : "true");			if(f) {				canreach = 1;				supgen(n->right->left);				oldreach = canreach;				canreach = 1;				gen(n->right->right);				/*				 * treat constant ifs as regular ifs for 				 * reachability warnings.				 */				if(!canreach && oldreach && debug['w'] < 2)					warnreach = 0;			}			else {				canreach = 1;				gen(n->right->left);				oldreach = canreach;				canreach = 1;				supgen(n->right->right);				/*				 * treat constant ifs as regular ifs for 				 * reachability warnings.				 */				if(!oldreach && canreach && debug['w'] < 2)					warnreach = 0;				canreach = oldreach;			}		}		else {			sp = p;			canreach = 1;			if(n->right->left != Z)				gen(n->right->left);			oldreach = canreach;			canreach = 1;			if(n->right->right != Z) {				gbranch(OGOTO);				patch(sp, pc);				sp = p;				gen(n->right->right);			}			patch(sp, pc);			canreach = canreach || oldreach;			if(canreach == 0)				warnreach = !suppress;		}		break;	case OSET:	case OUSED:		usedset(n->left, o);		break;	}}voidusedset(Node *n, int o){	if(n->op == OLIST) {		usedset(n->left, o);		usedset(n->right, o);		return;	}	complex(n);	switch(n->op) {	case OADDR:	/* volatile */		gins(ANOP, n, Z);		break;	case ONAME:		if(o == OSET)			gins(ANOP, Z, n);		else			gins(ANOP, n, Z);		break;	}}intbcomplex(Node *n, Node *c){	complex(n);	if(n->type != T)	if(tcompat(n, T, n->type, tnot))		n->type = T;	if(n->type == T) {		gbranch(OGOTO);		return 0;	}	if(c != Z && n->op == OCONST && deadheads(c))		return 1;	bool64(n);	boolgen(n, 1, Z);	return 0;}

⌨️ 快捷键说明

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