xref: /inferno-os/utils/tc/sgen.c (revision d67b7dad77bb8aa973dad1f7c3ab0c309b114278)
174a4d8c2SCharles.Forsyth #include "gc.h"
274a4d8c2SCharles.Forsyth 
374a4d8c2SCharles.Forsyth void
codgen(Node * n,Node * nn)474a4d8c2SCharles.Forsyth codgen(Node *n, Node *nn)
574a4d8c2SCharles.Forsyth {
674a4d8c2SCharles.Forsyth 	Prog *sp;
774a4d8c2SCharles.Forsyth 	Node *n1, nod, nod1;
874a4d8c2SCharles.Forsyth 
974a4d8c2SCharles.Forsyth 	cursafe = 0;
1074a4d8c2SCharles.Forsyth 	curarg = 0;
1174a4d8c2SCharles.Forsyth 	maxargsafe = 0;
1274a4d8c2SCharles.Forsyth 
1374a4d8c2SCharles.Forsyth 	/*
1474a4d8c2SCharles.Forsyth 	 * isolate name
1574a4d8c2SCharles.Forsyth 	 */
1674a4d8c2SCharles.Forsyth 	for(n1 = nn;; n1 = n1->left) {
1774a4d8c2SCharles.Forsyth 		if(n1 == Z) {
1874a4d8c2SCharles.Forsyth 			diag(nn, "cant find function name");
1974a4d8c2SCharles.Forsyth 			return;
2074a4d8c2SCharles.Forsyth 		}
2174a4d8c2SCharles.Forsyth 		if(n1->op == ONAME)
2274a4d8c2SCharles.Forsyth 			break;
2374a4d8c2SCharles.Forsyth 	}
2474a4d8c2SCharles.Forsyth 	nearln = nn->lineno;
2574a4d8c2SCharles.Forsyth 	gpseudo(ATEXT, n1->sym, nodconst(stkoff));
2674a4d8c2SCharles.Forsyth 	sp = p;
2774a4d8c2SCharles.Forsyth 	sp->reg |= ALLTHUMBS;	/* denotes thumb code */
2874a4d8c2SCharles.Forsyth 
2974a4d8c2SCharles.Forsyth 	/*
3074a4d8c2SCharles.Forsyth 	 * isolate first argument
3174a4d8c2SCharles.Forsyth 	 */
3274a4d8c2SCharles.Forsyth 	if(REGARG >= 0) {
3374a4d8c2SCharles.Forsyth 		if(typesuv[thisfn->link->etype]) {
3474a4d8c2SCharles.Forsyth 			nod1 = *nodret->left;
3574a4d8c2SCharles.Forsyth 			nodreg(&nod, &nod1, REGARG);
3674a4d8c2SCharles.Forsyth 			gopcode(OAS, &nod, Z, &nod1);
3774a4d8c2SCharles.Forsyth 		} else
3874a4d8c2SCharles.Forsyth 		if(firstarg && typechlp[firstargtype->etype]) {
3974a4d8c2SCharles.Forsyth 			nod1 = *nodret->left;
4074a4d8c2SCharles.Forsyth 			nod1.sym = firstarg;
4174a4d8c2SCharles.Forsyth 			nod1.type = firstargtype;
4274a4d8c2SCharles.Forsyth 			nod1.xoffset = align(0, firstargtype, Aarg1);
4374a4d8c2SCharles.Forsyth 			nod1.etype = firstargtype->etype;
4474a4d8c2SCharles.Forsyth 			nodreg(&nod, &nod1, REGARG);
4574a4d8c2SCharles.Forsyth 			gopcode(OAS, &nod, Z, &nod1);
4674a4d8c2SCharles.Forsyth 		}
4774a4d8c2SCharles.Forsyth 	}
4874a4d8c2SCharles.Forsyth 
4974a4d8c2SCharles.Forsyth 	retok = 0;
5074a4d8c2SCharles.Forsyth 	gen(n);
5174a4d8c2SCharles.Forsyth 	if(!retok)
5274a4d8c2SCharles.Forsyth 		if(thisfn->link->etype != TVOID)
5374a4d8c2SCharles.Forsyth 			warn(Z, "no return at end of function: %s", n1->sym->name);
5474a4d8c2SCharles.Forsyth 	noretval(3);
5574a4d8c2SCharles.Forsyth 	gbranch(ORETURN);
5674a4d8c2SCharles.Forsyth 
5774a4d8c2SCharles.Forsyth 	if(!debug['N'] || debug['R'] || debug['P'])
5874a4d8c2SCharles.Forsyth 		regopt(sp);
5974a4d8c2SCharles.Forsyth 
6074a4d8c2SCharles.Forsyth 	sp->to.offset += maxargsafe;
6174a4d8c2SCharles.Forsyth }
6274a4d8c2SCharles.Forsyth 
6374a4d8c2SCharles.Forsyth void
supgen(Node * n)6474a4d8c2SCharles.Forsyth supgen(Node *n)
6574a4d8c2SCharles.Forsyth {
6674a4d8c2SCharles.Forsyth 	long spc;
6774a4d8c2SCharles.Forsyth 	Prog *sp;
6874a4d8c2SCharles.Forsyth 
6974a4d8c2SCharles.Forsyth 	if(n == Z)
7074a4d8c2SCharles.Forsyth 		return;
7174a4d8c2SCharles.Forsyth 	suppress++;
7274a4d8c2SCharles.Forsyth 	spc = pc;
7374a4d8c2SCharles.Forsyth 	sp = lastp;
7474a4d8c2SCharles.Forsyth 	gen(n);
7574a4d8c2SCharles.Forsyth 	lastp = sp;
7674a4d8c2SCharles.Forsyth 	pc = spc;
7774a4d8c2SCharles.Forsyth 	sp->link = nil;
7874a4d8c2SCharles.Forsyth 	suppress--;
7974a4d8c2SCharles.Forsyth }
8074a4d8c2SCharles.Forsyth 
8174a4d8c2SCharles.Forsyth void
gen(Node * n)8274a4d8c2SCharles.Forsyth gen(Node *n)
8374a4d8c2SCharles.Forsyth {
8474a4d8c2SCharles.Forsyth 	Node *l, nod;
8574a4d8c2SCharles.Forsyth 	Prog *sp, *spc, *spb;
8674a4d8c2SCharles.Forsyth 	Case *cn;
8774a4d8c2SCharles.Forsyth 	long sbc, scc;
8874a4d8c2SCharles.Forsyth 	int o, f;
8974a4d8c2SCharles.Forsyth 
9074a4d8c2SCharles.Forsyth loop:
9174a4d8c2SCharles.Forsyth 	if(n == Z)
9274a4d8c2SCharles.Forsyth 		return;
9374a4d8c2SCharles.Forsyth 	nearln = n->lineno;
9474a4d8c2SCharles.Forsyth 	o = n->op;
9574a4d8c2SCharles.Forsyth 	if(debug['G'])
9674a4d8c2SCharles.Forsyth 		if(o != OLIST)
9774a4d8c2SCharles.Forsyth 			print("%L %O\n", nearln, o);
9874a4d8c2SCharles.Forsyth 
9974a4d8c2SCharles.Forsyth 	retok = 0;
10074a4d8c2SCharles.Forsyth 	switch(o) {
10174a4d8c2SCharles.Forsyth 
10274a4d8c2SCharles.Forsyth 	default:
10374a4d8c2SCharles.Forsyth 		complex(n);
10474a4d8c2SCharles.Forsyth 		cgen(n, Z);
10574a4d8c2SCharles.Forsyth 		break;
10674a4d8c2SCharles.Forsyth 
10774a4d8c2SCharles.Forsyth 	case OLIST:
10874a4d8c2SCharles.Forsyth 		gen(n->left);
10974a4d8c2SCharles.Forsyth 
11074a4d8c2SCharles.Forsyth 	rloop:
11174a4d8c2SCharles.Forsyth 		n = n->right;
11274a4d8c2SCharles.Forsyth 		goto loop;
11374a4d8c2SCharles.Forsyth 
11474a4d8c2SCharles.Forsyth 	case ORETURN:
11574a4d8c2SCharles.Forsyth 		retok = 1;
11674a4d8c2SCharles.Forsyth 		complex(n);
11774a4d8c2SCharles.Forsyth 		if(n->type == T)
11874a4d8c2SCharles.Forsyth 			break;
11974a4d8c2SCharles.Forsyth 		l = n->left;
12074a4d8c2SCharles.Forsyth 		if(l == Z) {
12174a4d8c2SCharles.Forsyth 			noretval(3);
12274a4d8c2SCharles.Forsyth 			gbranch(ORETURN);
12374a4d8c2SCharles.Forsyth 			break;
12474a4d8c2SCharles.Forsyth 		}
12574a4d8c2SCharles.Forsyth 		if(typesuv[n->type->etype]) {
12674a4d8c2SCharles.Forsyth 			sugen(l, nodret, n->type->width);
12774a4d8c2SCharles.Forsyth 			noretval(3);
12874a4d8c2SCharles.Forsyth 			gbranch(ORETURN);
12974a4d8c2SCharles.Forsyth 			break;
13074a4d8c2SCharles.Forsyth 		}
13174a4d8c2SCharles.Forsyth 		regret(&nod, n);
13274a4d8c2SCharles.Forsyth 		cgen(l, &nod);
13374a4d8c2SCharles.Forsyth 		regfree(&nod);
13474a4d8c2SCharles.Forsyth 		if(typefd[n->type->etype])
13574a4d8c2SCharles.Forsyth 			noretval(1);
13674a4d8c2SCharles.Forsyth 		else
13774a4d8c2SCharles.Forsyth 			noretval(2);
13874a4d8c2SCharles.Forsyth 		gbranch(ORETURN);
13974a4d8c2SCharles.Forsyth 		break;
14074a4d8c2SCharles.Forsyth 
14174a4d8c2SCharles.Forsyth 	case OLABEL:
14274a4d8c2SCharles.Forsyth 		l = n->left;
14374a4d8c2SCharles.Forsyth 		if(l) {
14474a4d8c2SCharles.Forsyth 			l->pc = pc;
14574a4d8c2SCharles.Forsyth 			if(l->label)
14674a4d8c2SCharles.Forsyth 				patch(l->label, pc);
14774a4d8c2SCharles.Forsyth 		}
14874a4d8c2SCharles.Forsyth 		gbranch(OGOTO);	/* prevent self reference in reg */
14974a4d8c2SCharles.Forsyth 		patch(p, pc);
15074a4d8c2SCharles.Forsyth 		goto rloop;
15174a4d8c2SCharles.Forsyth 
15274a4d8c2SCharles.Forsyth 	case OGOTO:
15374a4d8c2SCharles.Forsyth 		retok = 1;
15474a4d8c2SCharles.Forsyth 		n = n->left;
15574a4d8c2SCharles.Forsyth 		if(n == Z)
15674a4d8c2SCharles.Forsyth 			return;
15774a4d8c2SCharles.Forsyth 		if(n->complex == 0) {
15874a4d8c2SCharles.Forsyth 			diag(Z, "label undefined: %s", n->sym->name);
15974a4d8c2SCharles.Forsyth 			return;
16074a4d8c2SCharles.Forsyth 		}
16174a4d8c2SCharles.Forsyth 		if(suppress)
16274a4d8c2SCharles.Forsyth 			return;
16374a4d8c2SCharles.Forsyth 		gbranch(OGOTO);
16474a4d8c2SCharles.Forsyth 		if(n->pc) {
16574a4d8c2SCharles.Forsyth 			patch(p, n->pc);
16674a4d8c2SCharles.Forsyth 			return;
16774a4d8c2SCharles.Forsyth 		}
16874a4d8c2SCharles.Forsyth 		if(n->label)
16974a4d8c2SCharles.Forsyth 			patch(n->label, pc-1);
17074a4d8c2SCharles.Forsyth 		n->label = p;
17174a4d8c2SCharles.Forsyth 		return;
17274a4d8c2SCharles.Forsyth 
17374a4d8c2SCharles.Forsyth 	case OCASE:
17474a4d8c2SCharles.Forsyth 		l = n->left;
17574a4d8c2SCharles.Forsyth 		if(cases == C)
17674a4d8c2SCharles.Forsyth 			diag(n, "case/default outside a switch");
17774a4d8c2SCharles.Forsyth 		if(l == Z) {
178*d67b7dadSforsyth 			casf();
17974a4d8c2SCharles.Forsyth 			cases->val = 0;
18074a4d8c2SCharles.Forsyth 			cases->def = 1;
18174a4d8c2SCharles.Forsyth 			cases->label = pc;
18274a4d8c2SCharles.Forsyth 			goto rloop;
18374a4d8c2SCharles.Forsyth 		}
18474a4d8c2SCharles.Forsyth 		complex(l);
18574a4d8c2SCharles.Forsyth 		if(l->type == T)
18674a4d8c2SCharles.Forsyth 			goto rloop;
18774a4d8c2SCharles.Forsyth 		if(l->op == OCONST)
18874a4d8c2SCharles.Forsyth 		if(typechl[l->type->etype]) {
189*d67b7dadSforsyth 			casf();
19074a4d8c2SCharles.Forsyth 			cases->val = l->vconst;
19174a4d8c2SCharles.Forsyth 			cases->def = 0;
19274a4d8c2SCharles.Forsyth 			cases->label = pc;
19374a4d8c2SCharles.Forsyth 			goto rloop;
19474a4d8c2SCharles.Forsyth 		}
19574a4d8c2SCharles.Forsyth 		diag(n, "case expression must be integer constant");
19674a4d8c2SCharles.Forsyth 		goto rloop;
19774a4d8c2SCharles.Forsyth 
19874a4d8c2SCharles.Forsyth 	case OSWITCH:
19974a4d8c2SCharles.Forsyth 		l = n->left;
20074a4d8c2SCharles.Forsyth 		complex(l);
20174a4d8c2SCharles.Forsyth 		if(l->type == T)
20274a4d8c2SCharles.Forsyth 			break;
20374a4d8c2SCharles.Forsyth 		if(!typechl[l->type->etype]) {
20474a4d8c2SCharles.Forsyth 			diag(n, "switch expression must be integer");
20574a4d8c2SCharles.Forsyth 			break;
20674a4d8c2SCharles.Forsyth 		}
20774a4d8c2SCharles.Forsyth 
20874a4d8c2SCharles.Forsyth 		gbranch(OGOTO);		/* entry */
20974a4d8c2SCharles.Forsyth 		sp = p;
21074a4d8c2SCharles.Forsyth 
21174a4d8c2SCharles.Forsyth 		cn = cases;
21274a4d8c2SCharles.Forsyth 		cases = C;
213*d67b7dadSforsyth 		casf();
21474a4d8c2SCharles.Forsyth 
21574a4d8c2SCharles.Forsyth 		sbc = breakpc;
21674a4d8c2SCharles.Forsyth 		breakpc = pc;
21774a4d8c2SCharles.Forsyth 		gbranch(OGOTO);
21874a4d8c2SCharles.Forsyth 		spb = p;
21974a4d8c2SCharles.Forsyth 
22074a4d8c2SCharles.Forsyth 		gen(n->right);
22174a4d8c2SCharles.Forsyth 		gbranch(OGOTO);
22274a4d8c2SCharles.Forsyth 		patch(p, breakpc);
22374a4d8c2SCharles.Forsyth 
22474a4d8c2SCharles.Forsyth 		patch(sp, pc);
22574a4d8c2SCharles.Forsyth 		regalloc(&nod, l, Z);
22674a4d8c2SCharles.Forsyth 		nod.type = types[TLONG];
22774a4d8c2SCharles.Forsyth 		cgen(l, &nod);
22874a4d8c2SCharles.Forsyth 		doswit(&nod);
22974a4d8c2SCharles.Forsyth 		regfree(&nod);
23074a4d8c2SCharles.Forsyth 		patch(spb, pc);
23174a4d8c2SCharles.Forsyth 
23274a4d8c2SCharles.Forsyth 		cases = cn;
23374a4d8c2SCharles.Forsyth 		breakpc = sbc;
23474a4d8c2SCharles.Forsyth 		break;
23574a4d8c2SCharles.Forsyth 
23674a4d8c2SCharles.Forsyth 	case OWHILE:
23774a4d8c2SCharles.Forsyth 	case ODWHILE:
23874a4d8c2SCharles.Forsyth 		l = n->left;
23974a4d8c2SCharles.Forsyth 		gbranch(OGOTO);		/* entry */
24074a4d8c2SCharles.Forsyth 		sp = p;
24174a4d8c2SCharles.Forsyth 
24274a4d8c2SCharles.Forsyth 		scc = continpc;
24374a4d8c2SCharles.Forsyth 		continpc = pc;
24474a4d8c2SCharles.Forsyth 		gbranch(OGOTO);
24574a4d8c2SCharles.Forsyth 		spc = p;
24674a4d8c2SCharles.Forsyth 
24774a4d8c2SCharles.Forsyth 		sbc = breakpc;
24874a4d8c2SCharles.Forsyth 		breakpc = pc;
24974a4d8c2SCharles.Forsyth 		gbranch(OGOTO);
25074a4d8c2SCharles.Forsyth 		spb = p;
25174a4d8c2SCharles.Forsyth 
25274a4d8c2SCharles.Forsyth 		patch(spc, pc);
25374a4d8c2SCharles.Forsyth 		if(n->op == OWHILE)
25474a4d8c2SCharles.Forsyth 			patch(sp, pc);
25574a4d8c2SCharles.Forsyth 		bcomplex(l, Z);		/* test */
25674a4d8c2SCharles.Forsyth 		patch(p, breakpc);
25774a4d8c2SCharles.Forsyth 
25874a4d8c2SCharles.Forsyth 		if(n->op == ODWHILE)
25974a4d8c2SCharles.Forsyth 			patch(sp, pc);
26074a4d8c2SCharles.Forsyth 		gen(n->right);		/* body */
26174a4d8c2SCharles.Forsyth 		gbranch(OGOTO);
26274a4d8c2SCharles.Forsyth 		patch(p, continpc);
26374a4d8c2SCharles.Forsyth 
26474a4d8c2SCharles.Forsyth 		patch(spb, pc);
26574a4d8c2SCharles.Forsyth 		continpc = scc;
26674a4d8c2SCharles.Forsyth 		breakpc = sbc;
26774a4d8c2SCharles.Forsyth 		break;
26874a4d8c2SCharles.Forsyth 
26974a4d8c2SCharles.Forsyth 	case OFOR:
27074a4d8c2SCharles.Forsyth 		l = n->left;
27174a4d8c2SCharles.Forsyth 		gen(l->right->left);	/* init */
27274a4d8c2SCharles.Forsyth 		gbranch(OGOTO);		/* entry */
27374a4d8c2SCharles.Forsyth 		sp = p;
27474a4d8c2SCharles.Forsyth 
27574a4d8c2SCharles.Forsyth 		scc = continpc;
27674a4d8c2SCharles.Forsyth 		continpc = pc;
27774a4d8c2SCharles.Forsyth 		gbranch(OGOTO);
27874a4d8c2SCharles.Forsyth 		spc = p;
27974a4d8c2SCharles.Forsyth 
28074a4d8c2SCharles.Forsyth 		sbc = breakpc;
28174a4d8c2SCharles.Forsyth 		breakpc = pc;
28274a4d8c2SCharles.Forsyth 		gbranch(OGOTO);
28374a4d8c2SCharles.Forsyth 		spb = p;
28474a4d8c2SCharles.Forsyth 
28574a4d8c2SCharles.Forsyth 		patch(spc, pc);
28674a4d8c2SCharles.Forsyth 		gen(l->right->right);	/* inc */
28774a4d8c2SCharles.Forsyth 		patch(sp, pc);
28874a4d8c2SCharles.Forsyth 		if(l->left != Z) {	/* test */
28974a4d8c2SCharles.Forsyth 			bcomplex(l->left, Z);
29074a4d8c2SCharles.Forsyth 			patch(p, breakpc);
29174a4d8c2SCharles.Forsyth 		}
29274a4d8c2SCharles.Forsyth 		gen(n->right);		/* body */
29374a4d8c2SCharles.Forsyth 		gbranch(OGOTO);
29474a4d8c2SCharles.Forsyth 		patch(p, continpc);
29574a4d8c2SCharles.Forsyth 
29674a4d8c2SCharles.Forsyth 		patch(spb, pc);
29774a4d8c2SCharles.Forsyth 		continpc = scc;
29874a4d8c2SCharles.Forsyth 		breakpc = sbc;
29974a4d8c2SCharles.Forsyth 		break;
30074a4d8c2SCharles.Forsyth 
30174a4d8c2SCharles.Forsyth 	case OCONTINUE:
30274a4d8c2SCharles.Forsyth 		if(continpc < 0) {
30374a4d8c2SCharles.Forsyth 			diag(n, "continue not in a loop");
30474a4d8c2SCharles.Forsyth 			break;
30574a4d8c2SCharles.Forsyth 		}
30674a4d8c2SCharles.Forsyth 		gbranch(OGOTO);
30774a4d8c2SCharles.Forsyth 		patch(p, continpc);
30874a4d8c2SCharles.Forsyth 		break;
30974a4d8c2SCharles.Forsyth 
31074a4d8c2SCharles.Forsyth 	case OBREAK:
31174a4d8c2SCharles.Forsyth 		if(breakpc < 0) {
31274a4d8c2SCharles.Forsyth 			diag(n, "break not in a loop");
31374a4d8c2SCharles.Forsyth 			break;
31474a4d8c2SCharles.Forsyth 		}
31574a4d8c2SCharles.Forsyth 		gbranch(OGOTO);
31674a4d8c2SCharles.Forsyth 		patch(p, breakpc);
31774a4d8c2SCharles.Forsyth 		break;
31874a4d8c2SCharles.Forsyth 
31974a4d8c2SCharles.Forsyth 	case OIF:
32074a4d8c2SCharles.Forsyth 		l = n->left;
32174a4d8c2SCharles.Forsyth 		if(bcomplex(l, n->right)) {
32274a4d8c2SCharles.Forsyth 			if(typefd[l->type->etype])
32374a4d8c2SCharles.Forsyth 				f = !l->fconst;
32474a4d8c2SCharles.Forsyth 			else
32574a4d8c2SCharles.Forsyth 				f = !l->vconst;
32674a4d8c2SCharles.Forsyth 			if(debug['c'])
32774a4d8c2SCharles.Forsyth 				print("%L const if %s\n", nearln, f ? "false" : "true");
32874a4d8c2SCharles.Forsyth 			if(f) {
32974a4d8c2SCharles.Forsyth 				supgen(n->right->left);
33074a4d8c2SCharles.Forsyth 				gen(n->right->right);
33174a4d8c2SCharles.Forsyth 			}
33274a4d8c2SCharles.Forsyth 			else {
33374a4d8c2SCharles.Forsyth 				gen(n->right->left);
33474a4d8c2SCharles.Forsyth 				supgen(n->right->right);
33574a4d8c2SCharles.Forsyth 			}
33674a4d8c2SCharles.Forsyth 		}
33774a4d8c2SCharles.Forsyth 		else {
33874a4d8c2SCharles.Forsyth 			sp = p;
33974a4d8c2SCharles.Forsyth 			if(n->right->left != Z)
34074a4d8c2SCharles.Forsyth 				gen(n->right->left);
34174a4d8c2SCharles.Forsyth 			if(n->right->right != Z) {
34274a4d8c2SCharles.Forsyth 				gbranch(OGOTO);
34374a4d8c2SCharles.Forsyth 				patch(sp, pc);
34474a4d8c2SCharles.Forsyth 				sp = p;
34574a4d8c2SCharles.Forsyth 				gen(n->right->right);
34674a4d8c2SCharles.Forsyth 			}
34774a4d8c2SCharles.Forsyth 			patch(sp, pc);
34874a4d8c2SCharles.Forsyth 		}
34974a4d8c2SCharles.Forsyth 		break;
35074a4d8c2SCharles.Forsyth 
35174a4d8c2SCharles.Forsyth 	case OSET:
35274a4d8c2SCharles.Forsyth 	case OUSED:
35374a4d8c2SCharles.Forsyth 		usedset(n->left, o);
35474a4d8c2SCharles.Forsyth 		break;
35574a4d8c2SCharles.Forsyth 	}
35674a4d8c2SCharles.Forsyth }
35774a4d8c2SCharles.Forsyth 
35874a4d8c2SCharles.Forsyth void
usedset(Node * n,int o)35974a4d8c2SCharles.Forsyth usedset(Node *n, int o)
36074a4d8c2SCharles.Forsyth {
36174a4d8c2SCharles.Forsyth 	if(n->op == OLIST) {
36274a4d8c2SCharles.Forsyth 		usedset(n->left, o);
36374a4d8c2SCharles.Forsyth 		usedset(n->right, o);
36474a4d8c2SCharles.Forsyth 		return;
36574a4d8c2SCharles.Forsyth 	}
36674a4d8c2SCharles.Forsyth 	complex(n);
36774a4d8c2SCharles.Forsyth 	switch(n->op) {
36874a4d8c2SCharles.Forsyth 	case OADDR:	/* volatile */
36974a4d8c2SCharles.Forsyth 		gins(ANOP, n, Z);
37074a4d8c2SCharles.Forsyth 		break;
37174a4d8c2SCharles.Forsyth 	case ONAME:
37274a4d8c2SCharles.Forsyth 		if(o == OSET)
37374a4d8c2SCharles.Forsyth 			gins(ANOP, Z, n);
37474a4d8c2SCharles.Forsyth 		else
37574a4d8c2SCharles.Forsyth 			gins(ANOP, n, Z);
37674a4d8c2SCharles.Forsyth 		break;
37774a4d8c2SCharles.Forsyth 	}
37874a4d8c2SCharles.Forsyth }
37974a4d8c2SCharles.Forsyth 
38074a4d8c2SCharles.Forsyth void
noretval(int n)38174a4d8c2SCharles.Forsyth noretval(int n)
38274a4d8c2SCharles.Forsyth {
38374a4d8c2SCharles.Forsyth 
38474a4d8c2SCharles.Forsyth 	if(n & 1) {
38574a4d8c2SCharles.Forsyth 		gins(ANOP, Z, Z);
38674a4d8c2SCharles.Forsyth 		p->to.type = D_REG;
38774a4d8c2SCharles.Forsyth 		p->to.reg = REGRET;
38874a4d8c2SCharles.Forsyth 	}
38974a4d8c2SCharles.Forsyth 	if(n & 2) {
39074a4d8c2SCharles.Forsyth 		gins(ANOP, Z, Z);
39174a4d8c2SCharles.Forsyth 		p->to.type = D_FREG;
39274a4d8c2SCharles.Forsyth 		p->to.reg = FREGRET;
39374a4d8c2SCharles.Forsyth 	}
39474a4d8c2SCharles.Forsyth }
39574a4d8c2SCharles.Forsyth 
39674a4d8c2SCharles.Forsyth /*
39774a4d8c2SCharles.Forsyth  *	calculate addressability as follows
39874a4d8c2SCharles.Forsyth  *		CONST ==> 20		$value
39974a4d8c2SCharles.Forsyth  *		NAME ==> 10		name
40074a4d8c2SCharles.Forsyth  *		REGISTER ==> 11		register
40174a4d8c2SCharles.Forsyth  *		INDREG ==> 12		*[(reg)+offset]
40274a4d8c2SCharles.Forsyth  *		&10 ==> 2		$name
40374a4d8c2SCharles.Forsyth  *		ADD(2, 20) ==> 2	$name+offset
40474a4d8c2SCharles.Forsyth  *		ADD(3, 20) ==> 3	$(reg)+offset
40574a4d8c2SCharles.Forsyth  *		&12 ==> 3		$(reg)+offset
40674a4d8c2SCharles.Forsyth  *		*11 ==> 11		??
40774a4d8c2SCharles.Forsyth  *		*2 ==> 10		name
40874a4d8c2SCharles.Forsyth  *		*3 ==> 12		*(reg)+offset
40974a4d8c2SCharles.Forsyth  *	calculate complexity (number of registers)
41074a4d8c2SCharles.Forsyth  */
41174a4d8c2SCharles.Forsyth void
xcom(Node * n)41274a4d8c2SCharles.Forsyth xcom(Node *n)
41374a4d8c2SCharles.Forsyth {
41474a4d8c2SCharles.Forsyth 	Node *l, *r;
41574a4d8c2SCharles.Forsyth 	int t;
41674a4d8c2SCharles.Forsyth 
41774a4d8c2SCharles.Forsyth 	if(n == Z)
41874a4d8c2SCharles.Forsyth 		return;
41974a4d8c2SCharles.Forsyth 	l = n->left;
42074a4d8c2SCharles.Forsyth 	r = n->right;
42174a4d8c2SCharles.Forsyth 	n->addable = 0;
42274a4d8c2SCharles.Forsyth 	n->complex = 0;
42374a4d8c2SCharles.Forsyth 	switch(n->op) {
42474a4d8c2SCharles.Forsyth 	case OCONST:
42574a4d8c2SCharles.Forsyth 		n->addable = 20;
42674a4d8c2SCharles.Forsyth 		return;
42774a4d8c2SCharles.Forsyth 
42874a4d8c2SCharles.Forsyth 	case OREGISTER:
42974a4d8c2SCharles.Forsyth 		n->addable = 11;
43074a4d8c2SCharles.Forsyth 		return;
43174a4d8c2SCharles.Forsyth 
43274a4d8c2SCharles.Forsyth 	case OINDREG:
43374a4d8c2SCharles.Forsyth 		n->addable = 12;
43474a4d8c2SCharles.Forsyth 		return;
43574a4d8c2SCharles.Forsyth 
43674a4d8c2SCharles.Forsyth 	case ONAME:
43774a4d8c2SCharles.Forsyth 		n->addable = 10;
43874a4d8c2SCharles.Forsyth 		return;
43974a4d8c2SCharles.Forsyth 
44074a4d8c2SCharles.Forsyth 	case OADDR:
44174a4d8c2SCharles.Forsyth 		xcom(l);
44274a4d8c2SCharles.Forsyth 		if(l->addable == 10)
44374a4d8c2SCharles.Forsyth 			n->addable = 2;
44474a4d8c2SCharles.Forsyth 		if(l->addable == 12)
44574a4d8c2SCharles.Forsyth 			n->addable = 3;
44674a4d8c2SCharles.Forsyth 		break;
44774a4d8c2SCharles.Forsyth 
44874a4d8c2SCharles.Forsyth 	case OIND:
44974a4d8c2SCharles.Forsyth 		xcom(l);
45074a4d8c2SCharles.Forsyth 		if(l->addable == 11)
45174a4d8c2SCharles.Forsyth 			n->addable = 12;
45274a4d8c2SCharles.Forsyth 		if(l->addable == 3)
45374a4d8c2SCharles.Forsyth 			n->addable = 12;
45474a4d8c2SCharles.Forsyth 		if(l->addable == 2)
45574a4d8c2SCharles.Forsyth 			n->addable = 10;
45674a4d8c2SCharles.Forsyth 		break;
45774a4d8c2SCharles.Forsyth 
45874a4d8c2SCharles.Forsyth 	case OADD:
45974a4d8c2SCharles.Forsyth 		xcom(l);
46074a4d8c2SCharles.Forsyth 		xcom(r);
46174a4d8c2SCharles.Forsyth 		if(l->addable == 20) {
46274a4d8c2SCharles.Forsyth 			if(r->addable == 2)
46374a4d8c2SCharles.Forsyth 				n->addable = 2;
46474a4d8c2SCharles.Forsyth 			if(r->addable == 3)
46574a4d8c2SCharles.Forsyth 				n->addable = 3;
46674a4d8c2SCharles.Forsyth 		}
46774a4d8c2SCharles.Forsyth 		if(r->addable == 20) {
46874a4d8c2SCharles.Forsyth 			if(l->addable == 2)
46974a4d8c2SCharles.Forsyth 				n->addable = 2;
47074a4d8c2SCharles.Forsyth 			if(l->addable == 3)
47174a4d8c2SCharles.Forsyth 				n->addable = 3;
47274a4d8c2SCharles.Forsyth 		}
47374a4d8c2SCharles.Forsyth 		break;
47474a4d8c2SCharles.Forsyth 
47574a4d8c2SCharles.Forsyth /*
47674a4d8c2SCharles.Forsyth 	case OSUB:
47774a4d8c2SCharles.Forsyth 		xcom(l);
47874a4d8c2SCharles.Forsyth 		xcom(r);
47974a4d8c2SCharles.Forsyth 		if(typefd[n->type->etype] || typev[n->type->etype])
48074a4d8c2SCharles.Forsyth 			break;
48174a4d8c2SCharles.Forsyth 		if(vconst(l) == 0)
48274a4d8c2SCharles.Forsyth 			n->op = ONEG;
48374a4d8c2SCharles.Forsyth 			n->left = l;
48474a4d8c2SCharles.Forsyth 			n->right = Z;
48574a4d8c2SCharles.Forsyth 		}
48674a4d8c2SCharles.Forsyth 		break;
48774a4d8c2SCharles.Forsyth */
48874a4d8c2SCharles.Forsyth 
48974a4d8c2SCharles.Forsyth 	case OASHL:
49074a4d8c2SCharles.Forsyth 	case OASHR:
49174a4d8c2SCharles.Forsyth 	case OLSHR:
49274a4d8c2SCharles.Forsyth 	case OASASHL:
49374a4d8c2SCharles.Forsyth 	case OASASHR:
49474a4d8c2SCharles.Forsyth 	case OASLSHR:
49574a4d8c2SCharles.Forsyth 		xcom(l);
49674a4d8c2SCharles.Forsyth 		xcom(r);
49774a4d8c2SCharles.Forsyth 		if(sconst(r) && r->vconst < 0){
49874a4d8c2SCharles.Forsyth 			r->vconst = -r->vconst;
49974a4d8c2SCharles.Forsyth 			switch(n->op){
50074a4d8c2SCharles.Forsyth 			case OASHL:	n->op = OASHR; break;
50174a4d8c2SCharles.Forsyth 			case OASHR:	n->op = OASHL; break;
50274a4d8c2SCharles.Forsyth 			case OLSHR:	n->op = OASHL; break;
50374a4d8c2SCharles.Forsyth 			case OASASHL:	n->op = OASASHR; break;
50474a4d8c2SCharles.Forsyth 			case OASASHR:	n->op = OASASHL; break;
50574a4d8c2SCharles.Forsyth 			case OASLSHR:	n->op = OASASHL; break;
50674a4d8c2SCharles.Forsyth 			}
50774a4d8c2SCharles.Forsyth 		}
50874a4d8c2SCharles.Forsyth 		break;
50974a4d8c2SCharles.Forsyth 
51074a4d8c2SCharles.Forsyth 	case OASLMUL:
51174a4d8c2SCharles.Forsyth 	case OASMUL:
51274a4d8c2SCharles.Forsyth 		xcom(l);
51374a4d8c2SCharles.Forsyth 		xcom(r);
51474a4d8c2SCharles.Forsyth 		t = vlog(r);
51574a4d8c2SCharles.Forsyth 		if(t >= 0) {
51674a4d8c2SCharles.Forsyth 			n->op = OASASHL;
51774a4d8c2SCharles.Forsyth 			r->vconst = t;
51874a4d8c2SCharles.Forsyth 			r->type = types[TINT];
51974a4d8c2SCharles.Forsyth 		}
52074a4d8c2SCharles.Forsyth 		break;
52174a4d8c2SCharles.Forsyth 
52274a4d8c2SCharles.Forsyth 	case OMUL:
52374a4d8c2SCharles.Forsyth 	case OLMUL:
52474a4d8c2SCharles.Forsyth 		xcom(l);
52574a4d8c2SCharles.Forsyth 		xcom(r);
52674a4d8c2SCharles.Forsyth 		t = vlog(r);
52774a4d8c2SCharles.Forsyth 		if(t >= 0) {
52874a4d8c2SCharles.Forsyth 			n->op = OASHL;
52974a4d8c2SCharles.Forsyth 			r->vconst = t;
53074a4d8c2SCharles.Forsyth 			r->type = types[TINT];
53174a4d8c2SCharles.Forsyth 		}
53274a4d8c2SCharles.Forsyth 		t = vlog(l);
53374a4d8c2SCharles.Forsyth 		if(t >= 0) {
53474a4d8c2SCharles.Forsyth 			n->op = OASHL;
53574a4d8c2SCharles.Forsyth 			n->left = r;
53674a4d8c2SCharles.Forsyth 			n->right = l;
53774a4d8c2SCharles.Forsyth 			r = l;
53874a4d8c2SCharles.Forsyth 			l = n->left;
53974a4d8c2SCharles.Forsyth 			r->vconst = t;
54074a4d8c2SCharles.Forsyth 			r->type = types[TINT];
54174a4d8c2SCharles.Forsyth 		}
54274a4d8c2SCharles.Forsyth 		break;
54374a4d8c2SCharles.Forsyth 
54474a4d8c2SCharles.Forsyth 	case OASLDIV:
54574a4d8c2SCharles.Forsyth 		xcom(l);
54674a4d8c2SCharles.Forsyth 		xcom(r);
54774a4d8c2SCharles.Forsyth 		t = vlog(r);
54874a4d8c2SCharles.Forsyth 		if(t >= 0) {
54974a4d8c2SCharles.Forsyth 			n->op = OASLSHR;
55074a4d8c2SCharles.Forsyth 			r->vconst = t;
55174a4d8c2SCharles.Forsyth 			r->type = types[TINT];
55274a4d8c2SCharles.Forsyth 		}
55374a4d8c2SCharles.Forsyth 		break;
55474a4d8c2SCharles.Forsyth 
55574a4d8c2SCharles.Forsyth 	case OLDIV:
55674a4d8c2SCharles.Forsyth 		xcom(l);
55774a4d8c2SCharles.Forsyth 		xcom(r);
55874a4d8c2SCharles.Forsyth 		t = vlog(r);
55974a4d8c2SCharles.Forsyth 		if(t >= 0) {
56074a4d8c2SCharles.Forsyth 			n->op = OLSHR;
56174a4d8c2SCharles.Forsyth 			r->vconst = t;
56274a4d8c2SCharles.Forsyth 			r->type = types[TINT];
56374a4d8c2SCharles.Forsyth 		}
56474a4d8c2SCharles.Forsyth 		break;
56574a4d8c2SCharles.Forsyth 
56674a4d8c2SCharles.Forsyth 	case OASLMOD:
56774a4d8c2SCharles.Forsyth 		xcom(l);
56874a4d8c2SCharles.Forsyth 		xcom(r);
56974a4d8c2SCharles.Forsyth 		t = vlog(r);
57074a4d8c2SCharles.Forsyth 		if(t >= 0) {
57174a4d8c2SCharles.Forsyth 			n->op = OASAND;
57274a4d8c2SCharles.Forsyth 			r->vconst--;
57374a4d8c2SCharles.Forsyth 		}
57474a4d8c2SCharles.Forsyth 		break;
57574a4d8c2SCharles.Forsyth 
57674a4d8c2SCharles.Forsyth 	case OLMOD:
57774a4d8c2SCharles.Forsyth 		xcom(l);
57874a4d8c2SCharles.Forsyth 		xcom(r);
57974a4d8c2SCharles.Forsyth 		t = vlog(r);
58074a4d8c2SCharles.Forsyth 		if(t >= 0) {
58174a4d8c2SCharles.Forsyth 			n->op = OAND;
58274a4d8c2SCharles.Forsyth 			r->vconst--;
58374a4d8c2SCharles.Forsyth 		}
58474a4d8c2SCharles.Forsyth 		break;
58574a4d8c2SCharles.Forsyth 
58674a4d8c2SCharles.Forsyth 	default:
58774a4d8c2SCharles.Forsyth 		if(l != Z)
58874a4d8c2SCharles.Forsyth 			xcom(l);
58974a4d8c2SCharles.Forsyth 		if(r != Z)
59074a4d8c2SCharles.Forsyth 			xcom(r);
59174a4d8c2SCharles.Forsyth 		break;
59274a4d8c2SCharles.Forsyth 	}
59374a4d8c2SCharles.Forsyth 	if(n->addable >= 10)
59474a4d8c2SCharles.Forsyth 		return;
59574a4d8c2SCharles.Forsyth 
59674a4d8c2SCharles.Forsyth 	if(l != Z)
59774a4d8c2SCharles.Forsyth 		n->complex = l->complex;
59874a4d8c2SCharles.Forsyth 	if(r != Z) {
59974a4d8c2SCharles.Forsyth 		if(r->complex == n->complex)
60074a4d8c2SCharles.Forsyth 			n->complex = r->complex+1;
60174a4d8c2SCharles.Forsyth 		else
60274a4d8c2SCharles.Forsyth 		if(r->complex > n->complex)
60374a4d8c2SCharles.Forsyth 			n->complex = r->complex;
60474a4d8c2SCharles.Forsyth 	}
60574a4d8c2SCharles.Forsyth 	if(n->complex == 0)
60674a4d8c2SCharles.Forsyth 		n->complex++;
60774a4d8c2SCharles.Forsyth 
60874a4d8c2SCharles.Forsyth 	if(com64(n))
60974a4d8c2SCharles.Forsyth 		return;
61074a4d8c2SCharles.Forsyth 
61174a4d8c2SCharles.Forsyth 	switch(n->op) {
61274a4d8c2SCharles.Forsyth 	case OFUNC:
61374a4d8c2SCharles.Forsyth 		n->complex = FNX;
61474a4d8c2SCharles.Forsyth 		break;
61574a4d8c2SCharles.Forsyth 
61674a4d8c2SCharles.Forsyth 	case OLE:
61774a4d8c2SCharles.Forsyth 	case OLT:
61874a4d8c2SCharles.Forsyth 	case OGE:
61974a4d8c2SCharles.Forsyth 	case OGT:
62074a4d8c2SCharles.Forsyth 	case OHI:
62174a4d8c2SCharles.Forsyth 	case OHS:
62274a4d8c2SCharles.Forsyth 	case OLO:
62374a4d8c2SCharles.Forsyth 	case OLS:
62474a4d8c2SCharles.Forsyth 		/*
62574a4d8c2SCharles.Forsyth 		 * immediate operators, make const on right
62674a4d8c2SCharles.Forsyth 		 */
62774a4d8c2SCharles.Forsyth 		if(l->op == OCONST) {
62874a4d8c2SCharles.Forsyth 			n->left = r;
62974a4d8c2SCharles.Forsyth 			n->right = l;
63074a4d8c2SCharles.Forsyth 			n->op = invrel[relindex(n->op)];
63174a4d8c2SCharles.Forsyth 		}
63274a4d8c2SCharles.Forsyth 		break;
63374a4d8c2SCharles.Forsyth 
63474a4d8c2SCharles.Forsyth 	case OADD:
63574a4d8c2SCharles.Forsyth 	case OXOR:
63674a4d8c2SCharles.Forsyth 	case OAND:
63774a4d8c2SCharles.Forsyth 	case OOR:
63874a4d8c2SCharles.Forsyth 	case OEQ:
63974a4d8c2SCharles.Forsyth 	case ONE:
64074a4d8c2SCharles.Forsyth 		/*
64174a4d8c2SCharles.Forsyth 		 * immediate operators, make const on right
64274a4d8c2SCharles.Forsyth 		 */
64374a4d8c2SCharles.Forsyth 		if(l->op == OCONST) {
64474a4d8c2SCharles.Forsyth 			n->left = r;
64574a4d8c2SCharles.Forsyth 			n->right = l;
64674a4d8c2SCharles.Forsyth 		}
64774a4d8c2SCharles.Forsyth 		break;
64874a4d8c2SCharles.Forsyth 	}
64974a4d8c2SCharles.Forsyth }
65074a4d8c2SCharles.Forsyth 
65174a4d8c2SCharles.Forsyth int
bcomplex(Node * n,Node * c)65274a4d8c2SCharles.Forsyth bcomplex(Node *n, Node *c)
65374a4d8c2SCharles.Forsyth {
65474a4d8c2SCharles.Forsyth 
65574a4d8c2SCharles.Forsyth 	complex(n);
65674a4d8c2SCharles.Forsyth 	if(n->type != T)
65774a4d8c2SCharles.Forsyth 	if(tcompat(n, T, n->type, tnot))
65874a4d8c2SCharles.Forsyth 		n->type = T;
65974a4d8c2SCharles.Forsyth 	if(n->type != T) {
66074a4d8c2SCharles.Forsyth 		if(c != Z && n->op == OCONST && deadheads(c))
66174a4d8c2SCharles.Forsyth 			return 1;
66274a4d8c2SCharles.Forsyth 		bool64(n);
66374a4d8c2SCharles.Forsyth 		boolgen(n, 1, Z);
66474a4d8c2SCharles.Forsyth 	} else
66574a4d8c2SCharles.Forsyth 		gbranch(OGOTO);
66674a4d8c2SCharles.Forsyth 	return 0;
66774a4d8c2SCharles.Forsyth }
668