xref: /plan9/sys/src/cmd/cc/pgen.c (revision f38ffa1b6ee3235acacadf1ed72cbf6b2b6dad63)
14ac975e2SDavid du Colombier #include "gc.h"
24ac975e2SDavid du Colombier 
34ac975e2SDavid du Colombier void
codgen(Node * n,Node * nn)44ac975e2SDavid du Colombier codgen(Node *n, Node *nn)
54ac975e2SDavid du Colombier {
64ac975e2SDavid du Colombier 	Prog *sp;
74ac975e2SDavid du Colombier 	Node *n1, nod, nod1;
84ac975e2SDavid du Colombier 
94ac975e2SDavid du Colombier 	cursafe = 0;
104ac975e2SDavid du Colombier 	curarg = 0;
114ac975e2SDavid du Colombier 	maxargsafe = 0;
126891d857SDavid du Colombier 	hasdoubled = 0;
134ac975e2SDavid du Colombier 
144ac975e2SDavid du Colombier 	/*
154ac975e2SDavid du Colombier 	 * isolate name
164ac975e2SDavid du Colombier 	 */
174ac975e2SDavid du Colombier 	for(n1 = nn;; n1 = n1->left) {
184ac975e2SDavid du Colombier 		if(n1 == Z) {
194ac975e2SDavid du Colombier 			diag(nn, "cant find function name");
204ac975e2SDavid du Colombier 			return;
214ac975e2SDavid du Colombier 		}
224ac975e2SDavid du Colombier 		if(n1->op == ONAME)
234ac975e2SDavid du Colombier 			break;
244ac975e2SDavid du Colombier 	}
254ac975e2SDavid du Colombier 	nearln = nn->lineno;
264ac975e2SDavid du Colombier 	gpseudo(ATEXT, n1->sym, nodconst(stkoff));
274ac975e2SDavid du Colombier 	sp = p;
284ac975e2SDavid du Colombier 
296891d857SDavid du Colombier 	if(typecmplx[thisfn->link->etype]) {
306891d857SDavid du Colombier 		if(nodret == nil) {
316891d857SDavid du Colombier 			nodret = new(ONAME, Z, Z);
326891d857SDavid du Colombier 			nodret->sym = slookup(".ret");
336891d857SDavid du Colombier 			nodret->class = CPARAM;
346891d857SDavid du Colombier 			nodret->type = types[TIND];
356891d857SDavid du Colombier 			nodret->etype = TIND;
366891d857SDavid du Colombier 			nodret = new(OIND, nodret, Z);
376891d857SDavid du Colombier 		}
386891d857SDavid du Colombier 		n1 = nodret->left;
396891d857SDavid du Colombier 		if(n1->type == T || n1->type->link != thisfn->link) {
406891d857SDavid du Colombier 			n1->type = typ(TIND, thisfn->link);
416891d857SDavid du Colombier 			n1->etype = n1->type->etype;
426891d857SDavid du Colombier 			nodret = new(OIND, n1, Z);
436891d857SDavid du Colombier 			complex(nodret);
446891d857SDavid du Colombier 		}
456891d857SDavid du Colombier 	}
466891d857SDavid du Colombier 
474ac975e2SDavid du Colombier 	/*
484ac975e2SDavid du Colombier 	 * isolate first argument
494ac975e2SDavid du Colombier 	 */
504ac975e2SDavid du Colombier 	if(REGARG >= 0) {
514ac975e2SDavid du Colombier 		if(typecmplx[thisfn->link->etype]) {
524ac975e2SDavid du Colombier 			nod1 = *nodret->left;
534ac975e2SDavid du Colombier 			nodreg(&nod, &nod1, REGARG);
544ac975e2SDavid du Colombier 			gmove(&nod, &nod1);
554ac975e2SDavid du Colombier 		} else
564ac975e2SDavid du Colombier 		if(firstarg && typeword[firstargtype->etype]) {
576891d857SDavid du Colombier 			nod1 = znode;
586891d857SDavid du Colombier 			nod1.op = ONAME;
594ac975e2SDavid du Colombier 			nod1.sym = firstarg;
604ac975e2SDavid du Colombier 			nod1.type = firstargtype;
616891d857SDavid du Colombier 			nod1.class = CPARAM;
624ac975e2SDavid du Colombier 			nod1.xoffset = align(0, firstargtype, Aarg1);
634ac975e2SDavid du Colombier 			nod1.etype = firstargtype->etype;
646891d857SDavid du Colombier 			xcom(&nod1);
654ac975e2SDavid du Colombier 			nodreg(&nod, &nod1, REGARG);
664ac975e2SDavid du Colombier 			gmove(&nod, &nod1);
674ac975e2SDavid du Colombier 		}
684ac975e2SDavid du Colombier 	}
694ac975e2SDavid du Colombier 
70b85a8364SDavid du Colombier 	canreach = 1;
71b85a8364SDavid du Colombier 	warnreach = 1;
724ac975e2SDavid du Colombier 	gen(n);
733a276d32SDavid du Colombier 	if(canreach && thisfn->link->etype != TVOID){
743a276d32SDavid du Colombier 		if(debug['B'])
754ac975e2SDavid du Colombier 			warn(Z, "no return at end of function: %s", n1->sym->name);
763a276d32SDavid du Colombier 		else
773a276d32SDavid du Colombier 			diag(Z, "no return at end of function: %s", n1->sym->name);
783a276d32SDavid du Colombier 	}
794ac975e2SDavid du Colombier 	noretval(3);
804ac975e2SDavid du Colombier 	gbranch(ORETURN);
814ac975e2SDavid du Colombier 
824ac975e2SDavid du Colombier 	if(!debug['N'] || debug['R'] || debug['P'])
834ac975e2SDavid du Colombier 		regopt(sp);
844ac975e2SDavid du Colombier 
856891d857SDavid du Colombier 	if(thechar=='6' || thechar=='7' || thechar=='9' || hasdoubled)	/* [sic] */
864ac975e2SDavid du Colombier 		maxargsafe = round(maxargsafe, 8);
874ac975e2SDavid du Colombier 	sp->to.offset += maxargsafe;
884ac975e2SDavid du Colombier }
894ac975e2SDavid du Colombier 
904ac975e2SDavid du Colombier void
supgen(Node * n)914ac975e2SDavid du Colombier supgen(Node *n)
924ac975e2SDavid du Colombier {
93b85a8364SDavid du Colombier 	int owarn;
944ac975e2SDavid du Colombier 	long spc;
954ac975e2SDavid du Colombier 	Prog *sp;
964ac975e2SDavid du Colombier 
974ac975e2SDavid du Colombier 	if(n == Z)
984ac975e2SDavid du Colombier 		return;
994ac975e2SDavid du Colombier 	suppress++;
100b85a8364SDavid du Colombier 	owarn = warnreach;
101b85a8364SDavid du Colombier 	warnreach = 0;
1024ac975e2SDavid du Colombier 	spc = pc;
1034ac975e2SDavid du Colombier 	sp = lastp;
1044ac975e2SDavid du Colombier 	gen(n);
1054ac975e2SDavid du Colombier 	lastp = sp;
1064ac975e2SDavid du Colombier 	pc = spc;
1074ac975e2SDavid du Colombier 	sp->link = nil;
1084ac975e2SDavid du Colombier 	suppress--;
109b85a8364SDavid du Colombier 	warnreach = owarn;
1104ac975e2SDavid du Colombier }
1114ac975e2SDavid du Colombier 
112d40255d8SDavid du Colombier Node*
uncomma(Node * n)113d40255d8SDavid du Colombier uncomma(Node *n)
114d40255d8SDavid du Colombier {
115d40255d8SDavid du Colombier 	while(n != Z && n->op == OCOMMA) {
116d40255d8SDavid du Colombier 		cgen(n->left, Z);
117d40255d8SDavid du Colombier 		n = n->right;
118d40255d8SDavid du Colombier 	}
119d40255d8SDavid du Colombier 	return n;
120d40255d8SDavid du Colombier }
121d40255d8SDavid du Colombier 
1224ac975e2SDavid du Colombier void
gen(Node * n)1234ac975e2SDavid du Colombier gen(Node *n)
1244ac975e2SDavid du Colombier {
125d40255d8SDavid du Colombier 	Node *l, nod, rn;
1264ac975e2SDavid du Colombier 	Prog *sp, *spc, *spb;
1274ac975e2SDavid du Colombier 	Case *cn;
1284ac975e2SDavid du Colombier 	long sbc, scc;
129b85a8364SDavid du Colombier 	int snbreak, sncontin;
130b85a8364SDavid du Colombier 	int f, o, oldreach;
1314ac975e2SDavid du Colombier 
1324ac975e2SDavid du Colombier loop:
1334ac975e2SDavid du Colombier 	if(n == Z)
1344ac975e2SDavid du Colombier 		return;
1354ac975e2SDavid du Colombier 	nearln = n->lineno;
1364ac975e2SDavid du Colombier 	o = n->op;
1374ac975e2SDavid du Colombier 	if(debug['G'])
1384ac975e2SDavid du Colombier 		if(o != OLIST)
1394ac975e2SDavid du Colombier 			print("%L %O\n", nearln, o);
1404ac975e2SDavid du Colombier 
141b85a8364SDavid du Colombier 	if(!canreach) {
142b85a8364SDavid du Colombier 		switch(o) {
143b85a8364SDavid du Colombier 		case OLABEL:
144b85a8364SDavid du Colombier 		case OCASE:
145b85a8364SDavid du Colombier 		case OLIST:
146d40255d8SDavid du Colombier 		case OCOMMA:
147b85a8364SDavid du Colombier 		case OBREAK:
148b85a8364SDavid du Colombier 		case OFOR:
149b85a8364SDavid du Colombier 		case OWHILE:
150b85a8364SDavid du Colombier 		case ODWHILE:
151b85a8364SDavid du Colombier 			/* all handled specially - see switch body below */
152b85a8364SDavid du Colombier 			break;
153b85a8364SDavid du Colombier 		default:
154b85a8364SDavid du Colombier 			if(warnreach) {
155b85a8364SDavid du Colombier 				warn(n, "unreachable code %O", o);
156b85a8364SDavid du Colombier 				warnreach = 0;
157b85a8364SDavid du Colombier 			}
158b85a8364SDavid du Colombier 		}
159b85a8364SDavid du Colombier 	}
160b85a8364SDavid du Colombier 
1614ac975e2SDavid du Colombier 	switch(o) {
1624ac975e2SDavid du Colombier 
1634ac975e2SDavid du Colombier 	default:
1644ac975e2SDavid du Colombier 		complex(n);
1654ac975e2SDavid du Colombier 		cgen(n, Z);
1664ac975e2SDavid du Colombier 		break;
1674ac975e2SDavid du Colombier 
1684ac975e2SDavid du Colombier 	case OLIST:
169d40255d8SDavid du Colombier 	case OCOMMA:
1704ac975e2SDavid du Colombier 		gen(n->left);
1714ac975e2SDavid du Colombier 
1724ac975e2SDavid du Colombier 	rloop:
1734ac975e2SDavid du Colombier 		n = n->right;
1744ac975e2SDavid du Colombier 		goto loop;
1754ac975e2SDavid du Colombier 
1764ac975e2SDavid du Colombier 	case ORETURN:
177b85a8364SDavid du Colombier 		canreach = 0;
178b85a8364SDavid du Colombier 		warnreach = !suppress;
1794ac975e2SDavid du Colombier 		complex(n);
1804ac975e2SDavid du Colombier 		if(n->type == T)
1814ac975e2SDavid du Colombier 			break;
182d40255d8SDavid du Colombier 		l = uncomma(n->left);
1834ac975e2SDavid du Colombier 		if(l == Z) {
1844ac975e2SDavid du Colombier 			noretval(3);
1854ac975e2SDavid du Colombier 			gbranch(ORETURN);
1864ac975e2SDavid du Colombier 			break;
1874ac975e2SDavid du Colombier 		}
1884ac975e2SDavid du Colombier 		if(typecmplx[n->type->etype]) {
1896891d857SDavid du Colombier 			nod = znode;
1906891d857SDavid du Colombier 			nod.op = OAS;
1916891d857SDavid du Colombier 			nod.left = nodret;
1926891d857SDavid du Colombier 			nod.right = l;
1936891d857SDavid du Colombier 			nod.type = n->type;
1946891d857SDavid du Colombier 			nod.complex = l->complex;
1956891d857SDavid du Colombier 			cgen(&nod, Z);
1964ac975e2SDavid du Colombier 			noretval(3);
1974ac975e2SDavid du Colombier 			gbranch(ORETURN);
1984ac975e2SDavid du Colombier 			break;
1994ac975e2SDavid du Colombier 		}
200d40255d8SDavid du Colombier 		if(newvlongcode && !typefd[n->type->etype]){
201d40255d8SDavid du Colombier 			regret(&rn, n);
202d40255d8SDavid du Colombier 			regfree(&rn);
203d40255d8SDavid du Colombier 			nod = znode;
204d40255d8SDavid du Colombier 			nod.op = OAS;
205d40255d8SDavid du Colombier 			nod.left = &rn;
206d40255d8SDavid du Colombier 			nod.right = l;
207d40255d8SDavid du Colombier 			nod.type = n->type;
208d40255d8SDavid du Colombier 			nod.complex = l->complex;
209d40255d8SDavid du Colombier 			cgen(&nod, Z);
210d40255d8SDavid du Colombier 			noretval(2);
211d40255d8SDavid du Colombier 			gbranch(ORETURN);
212d40255d8SDavid du Colombier 			break;
213d40255d8SDavid du Colombier 		}
2144ac975e2SDavid du Colombier 		regret(&nod, n);
2154ac975e2SDavid du Colombier 		cgen(l, &nod);
2164ac975e2SDavid du Colombier 		regfree(&nod);
2174ac975e2SDavid du Colombier 		if(typefd[n->type->etype])
2184ac975e2SDavid du Colombier 			noretval(1);
2194ac975e2SDavid du Colombier 		else
2204ac975e2SDavid du Colombier 			noretval(2);
2214ac975e2SDavid du Colombier 		gbranch(ORETURN);
2224ac975e2SDavid du Colombier 		break;
2234ac975e2SDavid du Colombier 
2244ac975e2SDavid du Colombier 	case OLABEL:
225b85a8364SDavid du Colombier 		canreach = 1;
2264ac975e2SDavid du Colombier 		l = n->left;
2274ac975e2SDavid du Colombier 		if(l) {
2284ac975e2SDavid du Colombier 			l->pc = pc;
2294ac975e2SDavid du Colombier 			if(l->label)
2304ac975e2SDavid du Colombier 				patch(l->label, pc);
2314ac975e2SDavid du Colombier 		}
2324ac975e2SDavid du Colombier 		gbranch(OGOTO);	/* prevent self reference in reg */
2334ac975e2SDavid du Colombier 		patch(p, pc);
2344ac975e2SDavid du Colombier 		goto rloop;
2354ac975e2SDavid du Colombier 
2364ac975e2SDavid du Colombier 	case OGOTO:
237b85a8364SDavid du Colombier 		canreach = 0;
238b85a8364SDavid du Colombier 		warnreach = !suppress;
2394ac975e2SDavid du Colombier 		n = n->left;
2404ac975e2SDavid du Colombier 		if(n == Z)
2414ac975e2SDavid du Colombier 			return;
2424ac975e2SDavid du Colombier 		if(n->complex == 0) {
2434ac975e2SDavid du Colombier 			diag(Z, "label undefined: %s", n->sym->name);
2444ac975e2SDavid du Colombier 			return;
2454ac975e2SDavid du Colombier 		}
2464ac975e2SDavid du Colombier 		if(suppress)
2474ac975e2SDavid du Colombier 			return;
2484ac975e2SDavid du Colombier 		gbranch(OGOTO);
2494ac975e2SDavid du Colombier 		if(n->pc) {
2504ac975e2SDavid du Colombier 			patch(p, n->pc);
2514ac975e2SDavid du Colombier 			return;
2524ac975e2SDavid du Colombier 		}
2534ac975e2SDavid du Colombier 		if(n->label)
2544ac975e2SDavid du Colombier 			patch(n->label, pc-1);
2554ac975e2SDavid du Colombier 		n->label = p;
2564ac975e2SDavid du Colombier 		return;
2574ac975e2SDavid du Colombier 
2584ac975e2SDavid du Colombier 	case OCASE:
259b85a8364SDavid du Colombier 		canreach = 1;
2604ac975e2SDavid du Colombier 		l = n->left;
2614ac975e2SDavid du Colombier 		if(cases == C)
2624ac975e2SDavid du Colombier 			diag(n, "case/default outside a switch");
2634ac975e2SDavid du Colombier 		if(l == Z) {
264ff4cd143SDavid du Colombier 			casf();
2654ac975e2SDavid du Colombier 			cases->val = 0;
2664ac975e2SDavid du Colombier 			cases->def = 1;
2674ac975e2SDavid du Colombier 			cases->label = pc;
2685ede6b93SDavid du Colombier 			cases->isv = 0;
2694ac975e2SDavid du Colombier 			goto rloop;
2704ac975e2SDavid du Colombier 		}
2714ac975e2SDavid du Colombier 		complex(l);
2724ac975e2SDavid du Colombier 		if(l->type == T)
2734ac975e2SDavid du Colombier 			goto rloop;
2743a276d32SDavid du Colombier 		if(l->op != OCONST || !typeswitch[l->type->etype]) {
2753a276d32SDavid du Colombier 			diag(n, "case expression must be integer constant");
2763a276d32SDavid du Colombier 			goto rloop;
2773a276d32SDavid du Colombier 		}
278ff4cd143SDavid du Colombier 		casf();
2794ac975e2SDavid du Colombier 		cases->val = l->vconst;
2804ac975e2SDavid du Colombier 		cases->def = 0;
2814ac975e2SDavid du Colombier 		cases->label = pc;
2824ac975e2SDavid du Colombier 		cases->isv = typev[l->type->etype];
2834ac975e2SDavid du Colombier 		goto rloop;
2844ac975e2SDavid du Colombier 
2854ac975e2SDavid du Colombier 	case OSWITCH:
2864ac975e2SDavid du Colombier 		l = n->left;
2874ac975e2SDavid du Colombier 		complex(l);
2884ac975e2SDavid du Colombier 		if(l->type == T)
2894ac975e2SDavid du Colombier 			break;
2903a276d32SDavid du Colombier 		if(!typeswitch[l->type->etype]) {
2914ac975e2SDavid du Colombier 			diag(n, "switch expression must be integer");
2924ac975e2SDavid du Colombier 			break;
2934ac975e2SDavid du Colombier 		}
2944ac975e2SDavid du Colombier 
2954ac975e2SDavid du Colombier 		gbranch(OGOTO);		/* entry */
2964ac975e2SDavid du Colombier 		sp = p;
2974ac975e2SDavid du Colombier 
2984ac975e2SDavid du Colombier 		cn = cases;
2994ac975e2SDavid du Colombier 		cases = C;
300ff4cd143SDavid du Colombier 		casf();
3014ac975e2SDavid du Colombier 
3024ac975e2SDavid du Colombier 		sbc = breakpc;
3034ac975e2SDavid du Colombier 		breakpc = pc;
3044ac975e2SDavid du Colombier 		snbreak = nbreak;
3054ac975e2SDavid du Colombier 		nbreak = 0;
3064ac975e2SDavid du Colombier 		gbranch(OGOTO);
3074ac975e2SDavid du Colombier 		spb = p;
3084ac975e2SDavid du Colombier 
3094ac975e2SDavid du Colombier 		gen(n->right);		/* body */
310b85a8364SDavid du Colombier 		if(canreach){
3114ac975e2SDavid du Colombier 			gbranch(OGOTO);
3124ac975e2SDavid du Colombier 			patch(p, breakpc);
3134ac975e2SDavid du Colombier 			nbreak++;
3144ac975e2SDavid du Colombier 		}
3154ac975e2SDavid du Colombier 
3164ac975e2SDavid du Colombier 		patch(sp, pc);
3174ac975e2SDavid du Colombier 		regalloc(&nod, l, Z);
3184ac975e2SDavid du Colombier 		/* always signed */
3194ac975e2SDavid du Colombier 		if(typev[l->type->etype])
3204ac975e2SDavid du Colombier 			nod.type = types[TVLONG];
3214ac975e2SDavid du Colombier 		else
3224ac975e2SDavid du Colombier 			nod.type = types[TLONG];
3234ac975e2SDavid du Colombier 		cgen(l, &nod);
3244ac975e2SDavid du Colombier 		doswit(&nod);
3254ac975e2SDavid du Colombier 		regfree(&nod);
3264ac975e2SDavid du Colombier 		patch(spb, pc);
3274ac975e2SDavid du Colombier 
3284ac975e2SDavid du Colombier 		cases = cn;
3294ac975e2SDavid du Colombier 		breakpc = sbc;
330b85a8364SDavid du Colombier 		canreach = nbreak!=0;
331b85a8364SDavid du Colombier 		if(canreach == 0)
332b85a8364SDavid du Colombier 			warnreach = !suppress;
3334ac975e2SDavid du Colombier 		nbreak = snbreak;
3344ac975e2SDavid du Colombier 		break;
3354ac975e2SDavid du Colombier 
3364ac975e2SDavid du Colombier 	case OWHILE:
3374ac975e2SDavid du Colombier 	case ODWHILE:
3384ac975e2SDavid du Colombier 		l = n->left;
3394ac975e2SDavid du Colombier 		gbranch(OGOTO);		/* entry */
3404ac975e2SDavid du Colombier 		sp = p;
3414ac975e2SDavid du Colombier 
3424ac975e2SDavid du Colombier 		scc = continpc;
3434ac975e2SDavid du Colombier 		continpc = pc;
3444ac975e2SDavid du Colombier 		gbranch(OGOTO);
3454ac975e2SDavid du Colombier 		spc = p;
3464ac975e2SDavid du Colombier 
3474ac975e2SDavid du Colombier 		sbc = breakpc;
3484ac975e2SDavid du Colombier 		breakpc = pc;
3494ac975e2SDavid du Colombier 		snbreak = nbreak;
3504ac975e2SDavid du Colombier 		nbreak = 0;
3514ac975e2SDavid du Colombier 		gbranch(OGOTO);
3524ac975e2SDavid du Colombier 		spb = p;
3534ac975e2SDavid du Colombier 
3544ac975e2SDavid du Colombier 		patch(spc, pc);
3554ac975e2SDavid du Colombier 		if(n->op == OWHILE)
3564ac975e2SDavid du Colombier 			patch(sp, pc);
3574ac975e2SDavid du Colombier 		bcomplex(l, Z);		/* test */
3584ac975e2SDavid du Colombier 		patch(p, breakpc);
3594ac975e2SDavid du Colombier 		if(l->op != OCONST || vconst(l) == 0)
3604ac975e2SDavid du Colombier 			nbreak++;
3614ac975e2SDavid du Colombier 
3624ac975e2SDavid du Colombier 		if(n->op == ODWHILE)
3634ac975e2SDavid du Colombier 			patch(sp, pc);
3644ac975e2SDavid du Colombier 		gen(n->right);		/* body */
3654ac975e2SDavid du Colombier 		gbranch(OGOTO);
3664ac975e2SDavid du Colombier 		patch(p, continpc);
3674ac975e2SDavid du Colombier 
3684ac975e2SDavid du Colombier 		patch(spb, pc);
3694ac975e2SDavid du Colombier 		continpc = scc;
3704ac975e2SDavid du Colombier 		breakpc = sbc;
371b85a8364SDavid du Colombier 		canreach = nbreak!=0;
372b85a8364SDavid du Colombier 		if(canreach == 0)
373b85a8364SDavid du Colombier 			warnreach = !suppress;
3744ac975e2SDavid du Colombier 		nbreak = snbreak;
3754ac975e2SDavid du Colombier 		break;
3764ac975e2SDavid du Colombier 
3774ac975e2SDavid du Colombier 	case OFOR:
3784ac975e2SDavid du Colombier 		l = n->left;
379b85a8364SDavid du Colombier 		if(!canreach && l->right->left && warnreach) {
380b85a8364SDavid du Colombier 			warn(n, "unreachable code FOR");
381b85a8364SDavid du Colombier 			warnreach = 0;
382b85a8364SDavid du Colombier 		}
3834ac975e2SDavid du Colombier 		gen(l->right->left);	/* init */
3844ac975e2SDavid du Colombier 		gbranch(OGOTO);		/* entry */
3854ac975e2SDavid du Colombier 		sp = p;
3864ac975e2SDavid du Colombier 
387b85a8364SDavid du Colombier 		/*
388b85a8364SDavid du Colombier 		 * if there are no incoming labels in the
389b85a8364SDavid du Colombier 		 * body and the top's not reachable, warn
390b85a8364SDavid du Colombier 		 */
391b85a8364SDavid du Colombier 		if(!canreach && warnreach && deadheads(n)) {
392b85a8364SDavid du Colombier 			warn(n, "unreachable code %O", o);
393b85a8364SDavid du Colombier 			warnreach = 0;
394b85a8364SDavid du Colombier 		}
395b85a8364SDavid du Colombier 
3964ac975e2SDavid du Colombier 		scc = continpc;
3974ac975e2SDavid du Colombier 		continpc = pc;
3984ac975e2SDavid du Colombier 		gbranch(OGOTO);
3994ac975e2SDavid du Colombier 		spc = p;
4004ac975e2SDavid du Colombier 
4014ac975e2SDavid du Colombier 		sbc = breakpc;
4024ac975e2SDavid du Colombier 		breakpc = pc;
4034ac975e2SDavid du Colombier 		snbreak = nbreak;
4044ac975e2SDavid du Colombier 		nbreak = 0;
405b85a8364SDavid du Colombier 		sncontin = ncontin;
406b85a8364SDavid du Colombier 		ncontin = 0;
4074ac975e2SDavid du Colombier 		gbranch(OGOTO);
4084ac975e2SDavid du Colombier 		spb = p;
4094ac975e2SDavid du Colombier 
4104ac975e2SDavid du Colombier 		patch(spc, pc);
4114ac975e2SDavid du Colombier 		gen(l->right->right);	/* inc */
4124ac975e2SDavid du Colombier 		patch(sp, pc);
4134ac975e2SDavid du Colombier 		if(l->left != Z) {	/* test */
4144ac975e2SDavid du Colombier 			bcomplex(l->left, Z);
4154ac975e2SDavid du Colombier 			patch(p, breakpc);
4164ac975e2SDavid du Colombier 			if(l->left->op != OCONST || vconst(l->left) == 0)
4174ac975e2SDavid du Colombier 				nbreak++;
4184ac975e2SDavid du Colombier 		}
419b85a8364SDavid du Colombier 		canreach = 1;
4204ac975e2SDavid du Colombier 		gen(n->right);		/* body */
421b85a8364SDavid du Colombier 		if(canreach){
4224ac975e2SDavid du Colombier 			gbranch(OGOTO);
4234ac975e2SDavid du Colombier 			patch(p, continpc);
424b85a8364SDavid du Colombier 			ncontin++;
425b85a8364SDavid du Colombier 		}
426b85a8364SDavid du Colombier 		if(!ncontin && l->right->right && warnreach) {
427b85a8364SDavid du Colombier 			warn(l->right->right, "unreachable FOR inc");
428b85a8364SDavid du Colombier 			warnreach = 0;
429b85a8364SDavid du Colombier 		}
4304ac975e2SDavid du Colombier 
4314ac975e2SDavid du Colombier 		patch(spb, pc);
4324ac975e2SDavid du Colombier 		continpc = scc;
4334ac975e2SDavid du Colombier 		breakpc = sbc;
434b85a8364SDavid du Colombier 		canreach = nbreak!=0;
435b85a8364SDavid du Colombier 		if(canreach == 0)
436b85a8364SDavid du Colombier 			warnreach = !suppress;
4374ac975e2SDavid du Colombier 		nbreak = snbreak;
438b85a8364SDavid du Colombier 		ncontin = sncontin;
4394ac975e2SDavid du Colombier 		break;
4404ac975e2SDavid du Colombier 
4414ac975e2SDavid du Colombier 	case OCONTINUE:
4424ac975e2SDavid du Colombier 		if(continpc < 0) {
4434ac975e2SDavid du Colombier 			diag(n, "continue not in a loop");
4444ac975e2SDavid du Colombier 			break;
4454ac975e2SDavid du Colombier 		}
4464ac975e2SDavid du Colombier 		gbranch(OGOTO);
4474ac975e2SDavid du Colombier 		patch(p, continpc);
448b85a8364SDavid du Colombier 		ncontin++;
449b85a8364SDavid du Colombier 		canreach = 0;
450b85a8364SDavid du Colombier 		warnreach = !suppress;
4514ac975e2SDavid du Colombier 		break;
4524ac975e2SDavid du Colombier 
4534ac975e2SDavid du Colombier 	case OBREAK:
4544ac975e2SDavid du Colombier 		if(breakpc < 0) {
4554ac975e2SDavid du Colombier 			diag(n, "break not in a loop");
4564ac975e2SDavid du Colombier 			break;
4574ac975e2SDavid du Colombier 		}
458b85a8364SDavid du Colombier 		/*
459b85a8364SDavid du Colombier 		 * Don't complain about unreachable break statements.
460b85a8364SDavid du Colombier 		 * There are breaks hidden in yacc's output and some people
461b85a8364SDavid du Colombier 		 * write return; break; in their switch statements out of habit.
462b85a8364SDavid du Colombier 		 * However, don't confuse the analysis by inserting an
463b85a8364SDavid du Colombier 		 * unreachable reference to breakpc either.
464b85a8364SDavid du Colombier 		 */
465b85a8364SDavid du Colombier 		if(!canreach)
466b85a8364SDavid du Colombier 			break;
4674ac975e2SDavid du Colombier 		gbranch(OGOTO);
4684ac975e2SDavid du Colombier 		patch(p, breakpc);
4694ac975e2SDavid du Colombier 		nbreak++;
470b85a8364SDavid du Colombier 		canreach = 0;
471b85a8364SDavid du Colombier 		warnreach = !suppress;
4724ac975e2SDavid du Colombier 		break;
4734ac975e2SDavid du Colombier 
4744ac975e2SDavid du Colombier 	case OIF:
4754ac975e2SDavid du Colombier 		l = n->left;
4764ac975e2SDavid du Colombier 		if(bcomplex(l, n->right)) {
4774ac975e2SDavid du Colombier 			if(typefd[l->type->etype])
4784ac975e2SDavid du Colombier 				f = !l->fconst;
4794ac975e2SDavid du Colombier 			else
4804ac975e2SDavid du Colombier 				f = !l->vconst;
4814ac975e2SDavid du Colombier 			if(debug['c'])
4824ac975e2SDavid du Colombier 				print("%L const if %s\n", nearln, f ? "false" : "true");
4834ac975e2SDavid du Colombier 			if(f) {
484b85a8364SDavid du Colombier 				canreach = 1;
4854ac975e2SDavid du Colombier 				supgen(n->right->left);
486b85a8364SDavid du Colombier 				oldreach = canreach;
487b85a8364SDavid du Colombier 				canreach = 1;
4884ac975e2SDavid du Colombier 				gen(n->right->right);
489b85a8364SDavid du Colombier 				/*
490b85a8364SDavid du Colombier 				 * treat constant ifs as regular ifs for
491b85a8364SDavid du Colombier 				 * reachability warnings.
492b85a8364SDavid du Colombier 				 */
493b85a8364SDavid du Colombier 				if(!canreach && oldreach && debug['w'] < 2)
494b85a8364SDavid du Colombier 					warnreach = 0;
4954ac975e2SDavid du Colombier 			}
4964ac975e2SDavid du Colombier 			else {
497b85a8364SDavid du Colombier 				canreach = 1;
4984ac975e2SDavid du Colombier 				gen(n->right->left);
499b85a8364SDavid du Colombier 				oldreach = canreach;
500b85a8364SDavid du Colombier 				canreach = 1;
5014ac975e2SDavid du Colombier 				supgen(n->right->right);
502b85a8364SDavid du Colombier 				/*
503b85a8364SDavid du Colombier 				 * treat constant ifs as regular ifs for
504b85a8364SDavid du Colombier 				 * reachability warnings.
505b85a8364SDavid du Colombier 				 */
506b85a8364SDavid du Colombier 				if(!oldreach && canreach && debug['w'] < 2)
507b85a8364SDavid du Colombier 					warnreach = 0;
508b85a8364SDavid du Colombier 				canreach = oldreach;
5094ac975e2SDavid du Colombier 			}
5104ac975e2SDavid du Colombier 		}
5114ac975e2SDavid du Colombier 		else {
5124ac975e2SDavid du Colombier 			sp = p;
513b85a8364SDavid du Colombier 			canreach = 1;
5144ac975e2SDavid du Colombier 			if(n->right->left != Z)
5154ac975e2SDavid du Colombier 				gen(n->right->left);
516b85a8364SDavid du Colombier 			oldreach = canreach;
517b85a8364SDavid du Colombier 			canreach = 1;
5184ac975e2SDavid du Colombier 			if(n->right->right != Z) {
5194ac975e2SDavid du Colombier 				gbranch(OGOTO);
5204ac975e2SDavid du Colombier 				patch(sp, pc);
5214ac975e2SDavid du Colombier 				sp = p;
5224ac975e2SDavid du Colombier 				gen(n->right->right);
5234ac975e2SDavid du Colombier 			}
5244ac975e2SDavid du Colombier 			patch(sp, pc);
525b85a8364SDavid du Colombier 			canreach = canreach || oldreach;
526b85a8364SDavid du Colombier 			if(canreach == 0)
527b85a8364SDavid du Colombier 				warnreach = !suppress;
5284ac975e2SDavid du Colombier 		}
5294ac975e2SDavid du Colombier 		break;
5304ac975e2SDavid du Colombier 
5314ac975e2SDavid du Colombier 	case OSET:
5324ac975e2SDavid du Colombier 	case OUSED:
5334ac975e2SDavid du Colombier 		usedset(n->left, o);
5344ac975e2SDavid du Colombier 		break;
5354ac975e2SDavid du Colombier 	}
5364ac975e2SDavid du Colombier }
5374ac975e2SDavid du Colombier 
5384ac975e2SDavid du Colombier void
usedset(Node * n,int o)5394ac975e2SDavid du Colombier usedset(Node *n, int o)
5404ac975e2SDavid du Colombier {
5414ac975e2SDavid du Colombier 	if(n->op == OLIST) {
5424ac975e2SDavid du Colombier 		usedset(n->left, o);
5434ac975e2SDavid du Colombier 		usedset(n->right, o);
5444ac975e2SDavid du Colombier 		return;
5454ac975e2SDavid du Colombier 	}
5464ac975e2SDavid du Colombier 	complex(n);
5474ac975e2SDavid du Colombier 	switch(n->op) {
5484ac975e2SDavid du Colombier 	case OADDR:	/* volatile */
5494ac975e2SDavid du Colombier 		gins(ANOP, n, Z);
5504ac975e2SDavid du Colombier 		break;
5514ac975e2SDavid du Colombier 	case ONAME:
5524ac975e2SDavid du Colombier 		if(o == OSET)
5534ac975e2SDavid du Colombier 			gins(ANOP, Z, n);
5544ac975e2SDavid du Colombier 		else
5554ac975e2SDavid du Colombier 			gins(ANOP, n, Z);
5564ac975e2SDavid du Colombier 		break;
5574ac975e2SDavid du Colombier 	}
5584ac975e2SDavid du Colombier }
5594ac975e2SDavid du Colombier 
5604ac975e2SDavid du Colombier int
bcomplex(Node * n,Node * c)5614ac975e2SDavid du Colombier bcomplex(Node *n, Node *c)
5624ac975e2SDavid du Colombier {
563d40255d8SDavid du Colombier 	Node *b, nod;
564d40255d8SDavid du Colombier 
5654ac975e2SDavid du Colombier 
5664ac975e2SDavid du Colombier 	complex(n);
5674ac975e2SDavid du Colombier 	if(n->type != T)
5684ac975e2SDavid du Colombier 	if(tcompat(n, T, n->type, tnot))
5694ac975e2SDavid du Colombier 		n->type = T;
5704ac975e2SDavid du Colombier 	if(n->type == T) {
5714ac975e2SDavid du Colombier 		gbranch(OGOTO);
5724ac975e2SDavid du Colombier 		return 0;
5734ac975e2SDavid du Colombier 	}
5744ac975e2SDavid du Colombier 	if(c != Z && n->op == OCONST && deadheads(c))
5754ac975e2SDavid du Colombier 		return 1;
576*f38ffa1bSDavid du Colombier 	/* this is not quite right yet, so ignore it for now */
577*f38ffa1bSDavid du Colombier 	if(0 && newvlongcode && typev[n->type->etype] && machcap(Z)) {
578d40255d8SDavid du Colombier 		b = &nod;
579d40255d8SDavid du Colombier 		b->op = ONE;
580d40255d8SDavid du Colombier 		b->left = n;
581d40255d8SDavid du Colombier 		b->right = new(0, Z, Z);
582d40255d8SDavid du Colombier 		*b->right = *nodconst(0);
583d40255d8SDavid du Colombier 		b->right->type = n->type;
584d40255d8SDavid du Colombier 		b->type = types[TLONG];
585d40255d8SDavid du Colombier 		cgen(b, Z);
586d40255d8SDavid du Colombier 		return 0;
587d40255d8SDavid du Colombier 	}
5884ac975e2SDavid du Colombier 	bool64(n);
5894ac975e2SDavid du Colombier 	boolgen(n, 1, Z);
5904ac975e2SDavid du Colombier 	return 0;
5914ac975e2SDavid du Colombier }
592