xref: /inferno-os/limbo/ecom.c (revision e45fa0eb0763b57d6fb0649c064bc3b95ccdea6c)
1 #include "limbo.h"
2 
3 static Node* putinline(Node*);
4 static void fpcall(Src*, int, Node*, Node*);
5 
6 void
7 optabinit(void)
8 {
9 	int i;
10 
11 	for(i = 0; setisbyteinst[i] >= 0; i++)
12 		isbyteinst[setisbyteinst[i]] = 1;
13 
14 	for(i = 0; setisused[i] >= 0; i++)
15 		isused[setisused[i]] = 1;
16 
17 	for(i = 0; setsideeffect[i] >= 0; i++)
18 		sideeffect[setsideeffect[i]] = 1;
19 
20 	opind[Tbyte] = 1;
21 	opind[Tint] = 2;
22 	opind[Tbig] = 3;
23 	opind[Treal] = 4;
24 	opind[Tstring] = 5;
25 	opind[Tfix] = 6;
26 
27 	opcommute[Oeq] = Oeq;
28 	opcommute[Oneq] = Oneq;
29 	opcommute[Olt] = Ogt;
30 	opcommute[Ogt] = Olt;
31 	opcommute[Ogeq] = Oleq;
32 	opcommute[Oleq] = Ogeq;
33 	opcommute[Oadd] = Oadd;
34 	opcommute[Omul] = Omul;
35 	opcommute[Oxor] = Oxor;
36 	opcommute[Oor] = Oor;
37 	opcommute[Oand] = Oand;
38 
39 	oprelinvert[Oeq] = Oneq;
40 	oprelinvert[Oneq] = Oeq;
41 	oprelinvert[Olt] = Ogeq;
42 	oprelinvert[Ogt] = Oleq;
43 	oprelinvert[Ogeq] = Olt;
44 	oprelinvert[Oleq] = Ogt;
45 
46 	isrelop[Oeq] = 1;
47 	isrelop[Oneq] = 1;
48 	isrelop[Olt] = 1;
49 	isrelop[Oleq] = 1;
50 	isrelop[Ogt] = 1;
51 	isrelop[Ogeq] = 1;
52 	isrelop[Oandand] = 1;
53 	isrelop[Ooror] = 1;
54 	isrelop[Onot] = 1;
55 
56 	precasttab[Tstring][Tbyte] = tint;
57 	precasttab[Tbyte][Tstring] = tint;
58 	precasttab[Treal][Tbyte] = tint;
59 	precasttab[Tbyte][Treal] = tint;
60 	precasttab[Tbig][Tbyte] = tint;
61 	precasttab[Tbyte][Tbig] = tint;
62 	precasttab[Tfix][Tbyte] = tint;
63 	precasttab[Tbyte][Tfix] = tint;
64 	precasttab[Tbig][Tfix] = treal;
65 	precasttab[Tfix][Tbig] = treal;
66 	precasttab[Tstring][Tfix] = treal;
67 	precasttab[Tfix][Tstring] = treal;
68 
69 	casttab[Tint][Tint] = IMOVW;
70 	casttab[Tbig][Tbig] = IMOVL;
71 	casttab[Treal][Treal] = IMOVF;
72 	casttab[Tbyte][Tbyte] = IMOVB;
73 	casttab[Tstring][Tstring] = IMOVP;
74 	casttab[Tfix][Tfix] = ICVTXX;	/* never same type */
75 
76 	casttab[Tint][Tbyte] = ICVTWB;
77 	casttab[Tint][Treal] = ICVTWF;
78 	casttab[Tint][Tstring] = ICVTWC;
79 	casttab[Tint][Tfix] = ICVTXX;
80 	casttab[Tbyte][Tint] = ICVTBW;
81 	casttab[Treal][Tint] = ICVTFW;
82 	casttab[Tstring][Tint] = ICVTCW;
83 	casttab[Tfix][Tint] = ICVTXX;
84 
85 	casttab[Tint][Tbig] = ICVTWL;
86 	casttab[Treal][Tbig] = ICVTFL;
87 	casttab[Tstring][Tbig] = ICVTCL;
88 	casttab[Tbig][Tint] = ICVTLW;
89 	casttab[Tbig][Treal] = ICVTLF;
90 	casttab[Tbig][Tstring] = ICVTLC;
91 
92 	casttab[Treal][Tstring] = ICVTFC;
93 	casttab[Tstring][Treal] = ICVTCF;
94 
95 	casttab[Treal][Tfix] = ICVTFX;
96 	casttab[Tfix][Treal] = ICVTXF;
97 
98 	casttab[Tstring][Tarray] = ICVTCA;
99 	casttab[Tarray][Tstring] = ICVTAC;
100 
101 	/*
102 	 * placeholders; fixed in precasttab
103 	 */
104 	casttab[Tbyte][Tstring] = 0xff;
105 	casttab[Tstring][Tbyte] = 0xff;
106 	casttab[Tbyte][Treal] = 0xff;
107 	casttab[Treal][Tbyte] = 0xff;
108 	casttab[Tbyte][Tbig] = 0xff;
109 	casttab[Tbig][Tbyte] = 0xff;
110 	casttab[Tfix][Tbyte] = 0xff;
111 	casttab[Tbyte][Tfix] = 0xff;
112 	casttab[Tfix][Tbig] = 0xff;
113 	casttab[Tbig][Tfix] = 0xff;
114 	casttab[Tfix][Tstring] = 0xff;
115 	casttab[Tstring][Tfix] = 0xff;
116 }
117 
118 /*
119  * global variable and constant initialization checking
120  */
121 int
122 vcom(Decl *ids)
123 {
124 	Decl *v;
125 	int ok;
126 
127 	ok = 1;
128 	for(v = ids; v != nil; v = v->next)
129 		ok &= varcom(v);
130 	for(v = ids; v != nil; v = v->next)
131 		v->init = simplify(v->init);
132 	return ok;
133 }
134 
135 Node*
136 simplify(Node *n)
137 {
138 	if(n == nil)
139 		return nil;
140 	if(debug['F'])
141 		print("simplify %n\n", n);
142 	n = efold(rewrite(n));
143 	if(debug['F'])
144 		print("simplified %n\n", n);
145 	return n;
146 }
147 
148 static int
149 isfix(Node *n)
150 {
151 	if(n->ty->kind == Tint || n->ty->kind == Tfix){
152 		if(n->op == Ocast)
153 			return n->left->ty->kind == Tint || n->left->ty->kind == Tfix;
154 		return 1;
155 	}
156 	return 0;
157 }
158 
159 /*
160  * rewrite an expression to make it easiser to compile,
161  * or give the correct results
162  */
163 Node*
164 rewrite(Node *n)
165 {
166 	Long v;
167 	Type *t;
168 	Decl *d;
169 	Node *nn, *left, *right;
170 
171 	if(n == nil)
172 		return nil;
173 
174 	left = n->left;
175 	right = n->right;
176 
177 	/*
178 	 * rewrites
179 	 */
180 	switch(n->op){
181 	case Oname:
182 		d = n->decl;
183 		if(d->importid != nil){
184 			left = mkbin(Omdot, dupn(1, &n->src, d->eimport), mkdeclname(&n->src, d->importid));
185 			left->ty = n->ty;
186 			return rewrite(left);
187 		}
188 		if((t = n->ty)->kind == Texception){
189 			if(t->cons)
190 				fatal("cons in rewrite Oname");
191 			n = mkbin(Oadd, n, mkconst(&n->src, 2*IBY2WD));
192 			n = mkunary(Oind, n);
193 			n->ty = t;
194 			n->left->ty = n->left->left->ty = tint;
195 			return rewrite(n);
196 		}
197 		break;
198 	case Odas:
199 		n->op = Oas;
200 		return rewrite(n);
201 	case Oneg:
202 		n->left = rewrite(left);
203 		if(n->ty == treal)
204 			break;
205 		left = n->left;
206 		n->right = left;
207 		n->left = mkconst(&n->src, 0);
208 		n->left->ty = n->ty;
209 		n->op = Osub;
210 		break;
211 	case Ocomp:
212 		v = 0;
213 		v = ~v;
214 		n->right = mkconst(&n->src, v);
215 		n->right->ty = n->ty;
216 		n->left = rewrite(left);
217 		n->op = Oxor;
218 		break;
219 	case Oinc:
220 	case Odec:
221 	case Opreinc:
222 	case Opredec:
223 		n->left = rewrite(left);
224 		switch(n->ty->kind){
225 		case Treal:
226 			n->right = mkrconst(&n->src, 1.0);
227 			break;
228 		case Tint:
229 		case Tbig:
230 		case Tbyte:
231 		case Tfix:
232 			n->right = mkconst(&n->src, 1);
233 			n->right->ty = n->ty;
234 			break;
235 		default:
236 			fatal("can't rewrite inc/dec %n", n);
237 			break;
238 		}
239 		if(n->op == Opreinc)
240 			n->op = Oaddas;
241 		else if(n->op == Opredec)
242 			n->op = Osubas;
243 		break;
244 	case Oslice:
245 		if(right->left->op == Onothing)
246 			right->left = mkconst(&right->left->src, 0);
247 		n->left = rewrite(left);
248 		n->right = rewrite(right);
249 		break;
250 	case Oindex:
251 		n->op = Oindx;
252 		n->left = rewrite(left);
253 		n->right = rewrite(right);
254 		n = mkunary(Oind, n);
255 		n->ty = n->left->ty;
256 		n->left->ty = tint;
257 		break;
258 	case Oload:
259 		n->right = mkn(Oname, nil, nil);
260 		n->right->src = n->left->src;
261 		n->right->decl = n->ty->tof->decl;
262 		n->right->ty = n->ty;
263 		n->left = rewrite(left);
264 		break;
265 	case Ocast:
266 		if(left->ty->kind == Texception){
267 			n = rewrite(left);
268 			break;
269 		}
270 		n->op = Ocast;
271 		t = precasttab[left->ty->kind][n->ty->kind];
272 		if(t != nil){
273 			n->left = mkunary(Ocast, left);
274 			n->left->ty = t;
275 			return rewrite(n);
276 		}
277 		n->left = rewrite(left);
278 		break;
279 	case Oraise:
280 		if(left->ty == tstring)
281 			{}
282 		else if(!left->ty->cons)
283 			break;
284 		else if(left->op != Ocall || left->left->ty->kind == Tfn){
285 			left = mkunary(Ocall, left);
286 			left->ty = left->left->ty;
287 		}
288 		n->left = rewrite(left);
289 		break;
290 	case Ocall:
291 		t = left->ty;
292 		if(t->kind == Tref)
293 			t = t->tof;
294 		if(t->kind == Tfn){
295 if(debug['U']) print("call %n\n", left);
296 			if(left->ty->kind == Tref){	/* call by function reference */
297 				n->left = mkunary(Oind, left);
298 				n->left->ty = t;
299 				return rewrite(n);
300 			}
301 			d = nil;
302 			if(left->op == Oname)
303 				d = left->decl;
304 			else if(left->op == Omdot && left->right->op == Odot)
305 				d = left->right->right->decl;
306 			else if(left->op == Omdot || left->op == Odot)
307 				d = left->right->decl;
308 			else if(left->op != Oind)
309 				fatal("cannot deal with call %n in rewrite", n);
310 			if(ispoly(d))
311 				addfnptrs(d, 0);
312 			n->left = rewrite(left);
313 			if(right != nil)
314 				n->right = rewrite(right);
315 			if(d != nil && d->caninline == 1)
316 				n = simplify(putinline(n));
317 			break;
318 		}
319 		switch(n->ty->kind){
320 		case Tref:
321 			n = mkunary(Oref, n);
322 			n->ty = n->left->ty;
323 			n->left->ty = n->left->ty->tof;
324 			n->left->left->ty = n->left->ty;
325 			return rewrite(n);
326 		case Tadt:
327 			n->op = Otuple;
328 			n->right = nil;
329 			if(n->ty->tags != nil){
330 				n->left = nn = mkunary(Oseq, mkconst(&n->src, left->right->decl->tag));
331 				if(right != nil){
332 					nn->right = right;
333 					nn->src.stop = right->src.stop;
334 				}
335 				n->ty = left->right->decl->ty->tof;
336 			}else
337 				n->left = right;
338 			return rewrite(n);
339 		case Tadtpick:
340 			n->op = Otuple;
341 			n->right = nil;
342 			n->left = nn = mkunary(Oseq, mkconst(&n->src, left->right->decl->tag));
343 			if(right != nil){
344 				nn->right = right;
345 				nn->src.stop = right->src.stop;
346 			}
347 			n->ty = left->right->decl->ty->tof;
348 			return rewrite(n);
349 		case Texception:
350 			if(!n->ty->cons)
351 				return n->left;
352 			if(left->op == Omdot){
353 				left->right->ty = left->ty;
354 				left = left->right;
355 			}
356 			n->op = Otuple;
357 			n->right = nil;
358 			n->left = nn = mkunary(Oseq, left->decl->init);
359 			nn->right = mkunary(Oseq, mkconst(&n->src, 0));
360 			nn->right->right = right;
361 			n->ty = mkexbasetype(n->ty);
362 			n = mkunary(Oref, n);
363 			n->ty = internaltype(mktype(&n->src.start, &n->src.stop, Tref, t, nil));
364 			return rewrite(n);
365 		default:
366 			fatal("can't deal with %n in rewrite/Ocall", n);
367 			break;
368 		}
369 		break;
370 	case Omdot:
371 		/*
372 		 * what about side effects from left?
373 		 */
374 		d = right->decl;
375 		switch(d->store){
376 		case Dfn:
377 			n->left = rewrite(left);
378 			if(right->op == Odot){
379 				n->right = dupn(1, &left->src, right->right);
380 				n->right->ty = d->ty;
381 			}
382 			break;
383 		case Dconst:
384 		case Dtag:
385 		case Dtype:
386 			/* handled by fold */
387 			return n;
388 		case Dglobal:
389 			right->op = Oconst;
390 			right->val = d->offset;
391 			right->ty = tint;
392 
393 			n->left = left = mkunary(Oind, left);
394 			left->ty = tint;
395 			n->op = Oadd;
396 			n = mkunary(Oind, n);
397 			n->ty = n->left->ty;
398 			n->left->ty = tint;
399 			n->left = rewrite(n->left);
400 			return n;
401 		case Darg:
402 			return n;
403 		default:
404 			fatal("can't deal with %n in rewrite/Omdot", n);
405 			break;
406 		}
407 		break;
408 	case Odot:
409 		/*
410 		 * what about side effects from left?
411 		 */
412 		d = right->decl;
413 		switch(d->store){
414 		case Dfn:
415 			if(right->left != nil){
416 				n = mkbin(Omdot, dupn(1, &left->src, right->left), right);
417 				right->left = nil;
418 				n->ty = d->ty;
419 				return rewrite(n);
420 			}
421 			if(left->ty->kind == Tpoly){
422 				n = mkbin(Omdot, mkdeclname(&left->src, d->link), mkdeclname(&left->src, d->link->next));
423 				n->ty = d->ty;
424 				return rewrite(n);
425 			}
426 			n->op = Oname;
427 			n->decl = d;
428 			n->right = nil;
429 			n->left = nil;
430 			return n;
431 		case Dconst:
432 		case Dtag:
433 		case Dtype:
434 			/* handled by fold */
435 			return n;
436 		}
437 		if(istuple(left))
438 			return n;	/* handled by fold */
439 		right->op = Oconst;
440 		right->val = d->offset;
441 		right->ty = tint;
442 
443 		if(left->ty->kind != Tref){
444 			n->left = mkunary(Oadr, left);
445 			n->left->ty = tint;
446 		}
447 		n->op = Oadd;
448 		n = mkunary(Oind, n);
449 		n->ty = n->left->ty;
450 		n->left->ty = tint;
451 		n->left = rewrite(n->left);
452 		return n;
453 	case Oadr:
454 		left = rewrite(left);
455 		n->left = left;
456 		if(left->op == Oind)
457 			return left->left;
458 		break;
459 	case Otagof:
460 		if(n->decl == nil){
461 			n->op = Oind;
462 			return rewrite(n);
463 		}
464 		return n;
465 	case Omul:
466 	case Odiv:
467 		left = n->left = rewrite(left);
468 		right = n->right = rewrite(right);
469 		if(n->ty->kind == Tfix && isfix(left) && isfix(right)){
470 			if(left->op == Ocast && tequal(left->ty, n->ty))
471 				n->left = left->left;
472 			if(right->op == Ocast && tequal(right->ty, n->ty))
473 				n->right = right->left;
474 		}
475 		break;
476 	case Oself:
477 		if(newfnptr)
478 			return n;
479 		if(selfdecl == nil){
480 			d = selfdecl = mkids(&n->src, enter(strdup(".self"), 5), tany, nil);
481 			installids(Dglobal, d);
482 			d->refs++;
483 		}
484 		nn = mkn(Oload, nil, nil);
485 		nn->src = n->src;
486 		nn->left = mksconst(&n->src, enterstring(strdup("$self"), 5));
487 		nn->ty = impdecl->ty;
488 		usetype(nn->ty);
489 		usetype(nn->ty->tof);
490 		nn = rewrite(nn);
491 		nn->op = Oself;
492 		return nn;
493 	case Ofnptr:
494 		if(n->flags == 0){
495 			/* module */
496 			if(left == nil)
497 				left = mkn(Oself, nil, nil);
498 			return rewrite(left);
499 		}
500 		right->flags = n->flags;
501 		n = right;
502 		d = n->decl;
503 		if(n->flags == FNPTR2){
504 			if(left != nil && left->op != Oname)
505 				fatal("not Oname for addiface");
506 			if(left == nil){
507 				addiface(nil, d);
508 				if(newfnptr)
509 					n->flags |= FNPTRN;
510 			}
511 			else
512 				addiface(left->decl, d);	/* is this necessary ? */
513 			n->ty = tint;
514 			return n;
515 		}
516 		if(n->flags == FNPTRA){
517 			n = mkdeclname(&n->src, d->link);
518 			n->ty = tany;
519 			return n;
520 		}
521 		if(n->flags == (FNPTRA|FNPTR2)){
522 			n = mkdeclname(&n->src, d->link->next);
523 			n->ty = tint;
524 			return n;
525 		}
526 		break;
527 	case Ochan:
528 		if(left == nil)
529 			left = n->left = mkconst(&n->src, 0);
530 		n->left = rewrite(left);
531 		break;
532 	default:
533 		n->left = rewrite(left);
534 		n->right = rewrite(right);
535 		break;
536 	}
537 
538 	return n;
539 }
540 
541 /*
542  * label a node with sethi-ullman numbers and addressablity
543  * genaddr interprets addable to generate operands,
544  * so a change here mandates a change there.
545  *
546  * addressable:
547  *	const			Rconst	$value		 may also be Roff or Rdesc or Rnoff
548  *	Asmall(local)		Rreg	value(FP)
549  *	Asmall(global)		Rmreg	value(MP)
550  *	ind(Rareg)		Rreg	value(FP)
551  *	ind(Ramreg)		Rmreg	value(MP)
552  *	ind(Rreg)		Radr	*value(FP)
553  *	ind(Rmreg)		Rmadr	*value(MP)
554  *	ind(Raadr)		Radr	value(value(FP))
555  *	ind(Ramadr)		Rmadr	value(value(MP))
556  *
557  * almost addressable:
558  *	adr(Rreg)		Rareg
559  *	adr(Rmreg)		Ramreg
560  *	add(const, Rareg)	Rareg
561  *	add(const, Ramreg)	Ramreg
562  *	add(const, Rreg)	Raadr
563  *	add(const, Rmreg)	Ramadr
564  *	add(const, Raadr)	Raadr
565  *	add(const, Ramadr)	Ramadr
566  *	adr(Radr)		Raadr
567  *	adr(Rmadr)		Ramadr
568  *
569  * strangely addressable:
570  *	fn			Rpc
571  *	mdot(module,exp)	Rmpc
572  */
573 Node*
574 sumark(Node *n)
575 {
576 	Node *left, *right;
577 	long v;
578 
579 	if(n == nil)
580 		return nil;
581 
582 	n->temps = 0;
583 	n->addable = Rcant;
584 
585 	left = n->left;
586 	right = n->right;
587 	if(left != nil){
588 		sumark(left);
589 		n->temps = left->temps;
590 	}
591 	if(right != nil){
592 		sumark(right);
593 		if(right->temps == n->temps)
594 			n->temps++;
595 		else if(right->temps > n->temps)
596 			n->temps = right->temps;
597 	}
598 
599 	switch(n->op){
600 	case Oadr:
601 		switch(left->addable){
602 		case Rreg:
603 			n->addable = Rareg;
604 			break;
605 		case Rmreg:
606 			n->addable = Ramreg;
607 			break;
608 		case Radr:
609 			n->addable = Raadr;
610 			break;
611 		case Rmadr:
612 			n->addable = Ramadr;
613 			break;
614 		}
615 		break;
616 	case Oind:
617 		switch(left->addable){
618 		case Rreg:
619 			n->addable = Radr;
620 			break;
621 		case Rmreg:
622 			n->addable = Rmadr;
623 			break;
624 		case Rareg:
625 			n->addable = Rreg;
626 			break;
627 		case Ramreg:
628 			n->addable = Rmreg;
629 			break;
630 		case Raadr:
631 			n->addable = Radr;
632 			break;
633 		case Ramadr:
634 			n->addable = Rmadr;
635 			break;
636 		}
637 		break;
638 	case Oname:
639 		switch(n->decl->store){
640 		case Darg:
641 		case Dlocal:
642 			n->addable = Rreg;
643 			break;
644 		case Dglobal:
645 			n->addable = Rmreg;
646 			if(LDT && n->decl->ty->kind == Tiface)
647 				n->addable = Rldt;
648 			break;
649 		case Dtype:
650 			/*
651 			 * check for inferface to load
652 			 */
653 			if(n->decl->ty->kind == Tmodule)
654 				n->addable = Rmreg;
655 			break;
656 		case Dfn:
657 			if(n->flags & FNPTR){
658 				if(n->flags == FNPTR2)
659 					n->addable = Roff;
660 				else if(n->flags == (FNPTR2|FNPTRN))
661 					n->addable = Rnoff;
662 			}
663 			else
664 				n->addable = Rpc;
665 			break;
666 		default:
667 			fatal("cannot deal with %K in Oname in %n", n->decl, n);
668 			break;
669 		}
670 		break;
671 	case Omdot:
672 		n->addable = Rmpc;
673 		break;
674 	case Oconst:
675 		switch(n->ty->kind){
676 		case Tint:
677 		case Tfix:
678 			v = n->val;
679 			if(v < 0 && ((v >> 29) & 0x7) != 7
680 			|| v > 0 && (v >> 29) != 0){
681 				n->decl = globalconst(n);
682 				n->addable = Rmreg;
683 			}else
684 				n->addable = Rconst;
685 			break;
686 		case Tbig:
687 			n->decl = globalBconst(n);
688 			n->addable = Rmreg;
689 			break;
690 		case Tbyte:
691 			n->decl = globalbconst(n);
692 			n->addable = Rmreg;
693 			break;
694 		case Treal:
695 			n->decl = globalfconst(n);
696 			n->addable = Rmreg;
697 			break;
698 		case Tstring:
699 			n->decl = globalsconst(n);
700 			n->addable = Rmreg;
701 			break;
702 		default:
703 			fatal("cannot %T const in sumark", n->ty);
704 			break;
705 		}
706 		break;
707 	case Oadd:
708 		if(right->addable == Rconst){
709 			switch(left->addable){
710 			case Rareg:
711 				n->addable = Rareg;
712 				break;
713 			case Ramreg:
714 				n->addable = Ramreg;
715 				break;
716 			case Rreg:
717 			case Raadr:
718 				n->addable = Raadr;
719 				break;
720 			case Rmreg:
721 			case Ramadr:
722 				n->addable = Ramadr;
723 				break;
724 			}
725 		}
726 		break;
727 	}
728 	if(n->addable < Rcant)
729 		n->temps = 0;
730 	else if(n->temps == 0)
731 		n->temps = 1;
732 	return n;
733 }
734 
735 Node*
736 mktn(Type *t)
737 {
738 	Node *n;
739 
740 	n = mkn(Oname, nil, nil);
741 	usedesc(mktdesc(t));
742 	n->ty = t;
743 	n->decl = t->decl;
744 	if(n->decl == nil)
745 		fatal("mktn t %T nil decl", t);
746 	n->addable = Rdesc;
747 	return n;
748 }
749 
750 /* does a tuple of the form (a, b, ...) form a contiguous block
751  * of memory on the stack when offsets are assigned later
752  * - only when (a, b, ...) := rhs and none of the names nil
753  * can we guarantee this
754  */
755 static int
756 tupblk0(Node *n, Decl **dd)
757 {
758 	Decl *d;
759 	int nid;
760 
761 	switch(n->op){
762 	case Otuple:
763 		for(n = n->left; n != nil; n = n->right)
764 			if(!tupblk0(n->left, dd))
765 				return 0;
766 		return 1;
767 	case Oname:
768 		if(n->decl == nildecl)
769 			return 0;
770 		d = *dd;
771 		if(d != nil && d->next != n->decl)
772 			return 0;
773 		nid = n->decl->nid;
774 		if(d == nil && nid == 1)
775 			return 0;
776 		if(d != nil && nid != 0)
777 			return 0;
778 		*dd = n->decl;
779 		return 1;
780 	}
781 	return 0;
782 }
783 
784 /* could force locals to be next to each other
785  * - need to shuffle locals list
786  * - later
787  */
788 static Node*
789 tupblk(Node *n)
790 {
791 	Decl *d;
792 
793 	if(n->op != Otuple)
794 		return nil;
795 	d = nil;
796 	if(!tupblk0(n, &d))
797 		return nil;
798 	while(n->op == Otuple)
799 		n = n->left->left;
800 	if(n->op != Oname || n->decl->nid == 1)
801 		fatal("bad tupblk");
802 	return n;
803 }
804 
805 /* for cprof */
806 #define esrc(src, osrc, nto) (src != nil && nto != nil ? src : osrc)
807 
808 /*
809  * compile an expression with an implicit assignment
810  * note: you are not allowed to use to->src
811  *
812  * need to think carefully about the types used in moves
813  * it particular, it would be nice to gen movp rather than movc sometimes.
814  */
815 Node*
816 ecom(Src *src, Node *nto, Node *n)
817 {
818 	Node *left, *right, *tn;
819 	Node tl, tr, tto, ttn;
820 	Type *t, *tt;
821 	Inst *p, *pp;
822 	int op;
823 
824 	if(debug['e']){
825 		print("ecom: %n\n", n);
826 		if(nto != nil)
827 			print("ecom to: %n\n", nto);
828 	}
829 
830 	if(n->addable < Rcant){
831 		/*
832 		 * think carefully about the type used here
833 		 */
834 		if(nto != nil)
835 			genmove(src, Mas, n->ty, n, nto);
836 		return nto;
837 	}
838 
839 	tl.decl = nil;
840 	tr.decl = nil;
841 	tto.decl = nil;
842 	ttn.decl = nil;
843 
844 	left = n->left;
845 	right = n->right;
846 	op = n->op;
847 	switch(op){
848 	default:
849 	case Oadr:
850 		fatal("can't %n in ecom", n);
851 		return nto;
852 	case Oif:
853 		p = bcom(left, 1, nil);
854 		ecom(&right->left->src, nto, right->left);
855 		if(right->right != nil){
856 			pp = p;
857 			p = genrawop(&right->left->src, IJMP, nil, nil, nil);
858 			patch(pp, nextinst());
859 			ecom(&right->right->src, nto, right->right);
860 		}
861 		patch(p, nextinst());
862 		break;
863 	case Ocomma:
864 		tn = left->left;
865 		ecom(&left->src, nil, left);
866 		ecom(&right->src, nto, right);
867 		tfree(tn);
868 		break;
869 	case Oname:
870 		if(n->addable == Rpc){
871 			if(nto != nil)
872 				genmove(src, Mas, n->ty, n, nto);
873 			return nto;
874 		}
875 		fatal("can't %n in ecom", n);
876 		break;
877 	case Onothing:
878 		break;
879 	case Oused:
880 		if(nto != nil)
881 			fatal("superfluous used %n to %n", left, nto);
882 		talloc(&tto, left->ty, nil);
883 		ecom(&left->src, &tto, left);
884 		tfree(&tto);
885 		break;
886 	case Oas:
887 		if(right->ty == tany)
888 			right->ty = n->ty;
889 		if(left->op == Oname && left->decl->ty == tany){
890 			if(nto == nil)
891 				nto = talloc(&tto, right->ty, nil);
892 			left = nto;
893 			nto = nil;
894 		}
895 		if(left->op == Oinds){
896 			indsascom(src, nto, n);
897 			tfree(&tto);
898 			break;
899 		}
900 		if(left->op == Oslice){
901 			slicelcom(src, nto, n);
902 			tfree(&tto);
903 			break;
904 		}
905 
906 		if(left->op == Otuple){
907 			if(!tupsaliased(right, left)){
908 				if((tn = tupblk(left)) != nil){
909 					tn->ty = n->ty;
910 					ecom(&n->right->src, tn, right);
911 					if(nto != nil)
912 						genmove(src, Mas, n->ty, tn, nto);
913 					tfree(&tto);
914 					break;
915 				}
916 				if((tn = tupblk(right)) != nil){
917 					tn->ty = n->ty;
918 					tuplcom(tn, left);
919 					if(nto != nil)
920 						genmove(src, Mas, n->ty, tn, nto);
921 					tfree(&tto);
922 					break;
923 				}
924 				if(nto == nil && right->op == Otuple && left->ty->kind != Tadtpick){
925 					tuplrcom(right, left);
926 					tfree(&tto);
927 					break;
928 				}
929 			}
930 			if(right->addable >= Ralways
931 			|| right->op != Oname
932 			|| tupaliased(right, left)){
933 				talloc(&tr, n->ty, nil);
934 				ecom(&n->right->src, &tr, right);
935 				right = &tr;
936 			}
937 			tuplcom(right, n->left);
938 			if(nto != nil)
939 				genmove(src, Mas, n->ty, right, nto);
940 			tfree(&tr);
941 			tfree(&tto);
942 			break;
943 		}
944 
945 		/*
946 		 * check for left/right aliasing and build right into temporary
947 		 */
948 		if(right->op == Otuple){
949 			if(!tupsaliased(left, right) && (tn = tupblk(right)) != nil){
950 				tn->ty = n->ty;
951 				right = tn;
952 			}
953 			else if(left->op != Oname || tupaliased(left, right))
954 				right = ecom(&right->src, talloc(&tr, right->ty, nil), right);
955 		}
956 
957 		/*
958 		 * think carefully about types here
959 		 */
960 		if(left->addable >= Rcant)
961 			left = eacom(left, &tl, nto);
962 		ecom(&n->src, left, right);
963 		if(nto != nil)
964 			genmove(src, Mas, nto->ty, left, nto);
965 		tfree(&tl);
966 		tfree(&tr);
967 		tfree(&tto);
968 		break;
969 	case Ochan:
970 		if(left && left->addable >= Rcant)
971 			left = eacom(left, &tl, nto);
972 		genchan(src, left, n->ty->tof, nto);
973 		tfree(&tl);
974 		break;
975 	case Oinds:
976 		if(right->addable < Ralways){
977 			if(left->addable >= Rcant)
978 				left = eacom(left, &tl, nil);
979 		}else if(left->temps <= right->temps){
980 			right = ecom(&right->src, talloc(&tr, right->ty, nil), right);
981 			if(left->addable >= Rcant)
982 				left = eacom(left, &tl, nil);
983 		}else{
984 			left = eacom(left, &tl, nil);
985 			right = ecom(&right->src, talloc(&tr, right->ty, nil), right);
986 		}
987 		genop(&n->src, op, left, right, nto);
988 		tfree(&tl);
989 		tfree(&tr);
990 		break;
991 	case Osnd:
992 		if(right->addable < Rcant){
993 			if(left->addable >= Rcant)
994 				left = eacom(left, &tl, nto);
995 		}else if(left->temps < right->temps){
996 			right = eacom(right, &tr, nto);
997 			if(left->addable >= Rcant)
998 				left = eacom(left, &tl, nil);
999 		}else{
1000 			left = eacom(left, &tl, nto);
1001 			right = eacom(right, &tr, nil);
1002 		}
1003 		p = genrawop(&n->src, ISEND, right, nil, left);
1004 		p->m.offset = n->ty->size;	/* for optimizer */
1005 		if(nto != nil)
1006 			genmove(src, Mas, right->ty, right, nto);
1007 		tfree(&tl);
1008 		tfree(&tr);
1009 		break;
1010 	case Orcv:
1011 		if(nto == nil){
1012 			ecom(&n->src, talloc(&tto, n->ty, nil), n);
1013 			tfree(&tto);
1014 			return nil;
1015 		}
1016 		if(left->addable >= Rcant)
1017 			left = eacom(left, &tl, nto);
1018 		if(left->ty->kind == Tchan){
1019 			p = genrawop(src, IRECV, left, nil, nto);
1020 			p->m.offset = n->ty->size;	/* for optimizer */
1021 		}else{
1022 			recvacom(src, nto, n);
1023 		}
1024 		tfree(&tl);
1025 		break;
1026 	case Ocons:
1027 		/*
1028 		 * another temp which can go with analysis
1029 		 */
1030 		if(left->addable >= Rcant)
1031 			left = eacom(left, &tl, nil);
1032 		if(!sameaddr(right, nto)){
1033 			ecom(&right->src, talloc(&tto, n->ty, nto), right);
1034 			genmove(src, Mcons, left->ty, left, &tto);
1035 			if(!sameaddr(&tto, nto))
1036 				genmove(src, Mas, nto->ty, &tto, nto);
1037 		}else
1038 			genmove(src, Mcons, left->ty, left, nto);
1039 		tfree(&tl);
1040 		tfree(&tto);
1041 		break;
1042 	case Ohd:
1043 		if(left->addable >= Rcant)
1044 			left = eacom(left, &tl, nto);
1045 		genmove(src, Mhd, nto->ty, left, nto);
1046 		tfree(&tl);
1047 		break;
1048 	case Otl:
1049 		if(left->addable >= Rcant)
1050 			left = eacom(left, &tl, nto);
1051 		genmove(src, Mtl, left->ty, left, nto);
1052 		tfree(&tl);
1053 		break;
1054 	case Otuple:
1055 		if((tn = tupblk(n)) != nil){
1056 			tn->ty = n->ty;
1057 			genmove(src, Mas, n->ty, tn, nto);
1058 			break;
1059 		}
1060 		tupcom(nto, n);
1061 		break;
1062 	case Oadd:
1063 	case Osub:
1064 	case Omul:
1065 	case Odiv:
1066 	case Omod:
1067 	case Oand:
1068 	case Oor:
1069 	case Oxor:
1070 	case Olsh:
1071 	case Orsh:
1072 	case Oexp:
1073 		/*
1074 		 * check for 2 operand forms
1075 		 */
1076 		if(sameaddr(nto, left)){
1077 			if(right->addable >= Rcant)
1078 				right = eacom(right, &tr, nto);
1079 			genop(src, op, right, nil, nto);
1080 			tfree(&tr);
1081 			break;
1082 		}
1083 
1084 		if(opcommute[op] && sameaddr(nto, right) && n->ty != tstring){
1085 			if(left->addable >= Rcant)
1086 				left = eacom(left, &tl, nto);
1087 			genop(src, opcommute[op], left, nil, nto);
1088 			tfree(&tl);
1089 			break;
1090 		}
1091 
1092 		if(right->addable < left->addable
1093 		&& opcommute[op]
1094 		&& n->ty != tstring){
1095 			op = opcommute[op];
1096 			left = right;
1097 			right = n->left;
1098 		}
1099 		if(left->addable < Ralways){
1100 			if(right->addable >= Rcant)
1101 				right = eacom(right, &tr, nto);
1102 		}else if(right->temps <= left->temps){
1103 			left = ecom(&left->src, talloc(&tl, left->ty, nto), left);
1104 			if(right->addable >= Rcant)
1105 				right = eacom(right, &tr, nil);
1106 		}else{
1107 			right = eacom(right, &tr, nto);
1108 			left = ecom(&left->src, talloc(&tl, left->ty, nil), left);
1109 		}
1110 
1111 		/*
1112 		 * check for 2 operand forms
1113 		 */
1114 		if(sameaddr(nto, left))
1115 			genop(src, op, right, nil, nto);
1116 		else if(opcommute[op] && sameaddr(nto, right) && n->ty != tstring)
1117 			genop(src, opcommute[op], left, nil, nto);
1118 		else
1119 			genop(src, op, right, left, nto);
1120 		tfree(&tl);
1121 		tfree(&tr);
1122 		break;
1123 	case Oaddas:
1124 	case Osubas:
1125 	case Omulas:
1126 	case Odivas:
1127 	case Omodas:
1128 	case Oexpas:
1129 	case Oandas:
1130 	case Ooras:
1131 	case Oxoras:
1132 	case Olshas:
1133 	case Orshas:
1134 		if(left->op == Oinds){
1135 			indsascom(src, nto, n);
1136 			break;
1137 		}
1138 		if(right->addable < Rcant){
1139 			if(left->addable >= Rcant)
1140 				left = eacom(left, &tl, nto);
1141 		}else if(left->temps < right->temps){
1142 			right = eacom(right, &tr, nto);
1143 			if(left->addable >= Rcant)
1144 				left = eacom(left, &tl, nil);
1145 		}else{
1146 			left = eacom(left, &tl, nto);
1147 			right = eacom(right, &tr, nil);
1148 		}
1149 		genop(&n->src, op, right, nil, left);
1150 		if(nto != nil)
1151 			genmove(src, Mas, left->ty, left, nto);
1152 		tfree(&tl);
1153 		tfree(&tr);
1154 		break;
1155 	case Olen:
1156 		if(left->addable >= Rcant)
1157 			left = eacom(left, &tl, nto);
1158 		op = -1;
1159 		t = left->ty;
1160 		if(t == tstring)
1161 			op = ILENC;
1162 		else if(t->kind == Tarray)
1163 			op = ILENA;
1164 		else if(t->kind == Tlist)
1165 			op = ILENL;
1166 		else
1167 			fatal("can't len %n", n);
1168 		genrawop(src, op, left, nil, nto);
1169 		tfree(&tl);
1170 		break;
1171 	case Oneg:
1172 		if(left->addable >= Rcant)
1173 			left = eacom(left, &tl, nto);
1174 		genop(&n->src, op, left, nil, nto);
1175 		tfree(&tl);
1176 		break;
1177 	case Oinc:
1178 	case Odec:
1179 		if(left->op == Oinds){
1180 			indsascom(src, nto, n);
1181 			break;
1182 		}
1183 		if(left->addable >= Rcant)
1184 			left = eacom(left, &tl, nil);
1185 		if(nto != nil)
1186 			genmove(src, Mas, left->ty, left, nto);
1187 		if(right->addable >= Rcant)
1188 			fatal("inc/dec amount not addressable: %n", n);
1189 		genop(&n->src, op, right, nil, left);
1190 		tfree(&tl);
1191 		break;
1192 	case Ospawn:
1193 		if(left->left->op == Oind)
1194 			fpcall(&n->src, op, left, nto);
1195 		else
1196 			callcom(&n->src, op, left, nto);
1197 		break;
1198 	case Oraise:
1199 		if(left->addable >= Rcant)
1200 			left = eacom(left, &tl, nil);
1201 		genrawop(&n->src, IRAISE, left, nil, nil);
1202 		tfree(&tl);
1203 		break;
1204 	case Ocall:
1205 		if(left->op == Oind)
1206 			fpcall(esrc(src, &n->src, nto), op, n, nto);
1207 		else
1208 			callcom(esrc(src, &n->src, nto), op, n, nto);
1209 		break;
1210 	case Oref:
1211 		t = left->ty;
1212 		if(left->op == Oname && left->decl->store == Dfn || left->op == Omdot && left->right->op == Oname && left->right->decl->store == Dfn){	/* create a function reference */
1213 			Decl *d;
1214 			Node *mod, *ind;
1215 
1216 			d = left->decl;
1217 			if(left->op == Omdot){
1218 				d = left->right->decl;
1219 				mod = left->left;
1220 			}
1221 			else if(d->eimport != nil)
1222 				mod = d->eimport;
1223 			else{
1224 				mod = rewrite(mkn(Oself, nil, nil));
1225 				addiface(nil, d);
1226 			}
1227 			sumark(mod);
1228 			talloc(&tto, n->ty, nto);
1229 			genrawop(src, INEW, mktn(usetype(tfnptr)), nil, &tto);
1230 			tr.src = *src;
1231 			tr.op = Oind;
1232 			tr.left = &tto;
1233 			tr.right = nil;
1234 			tr.ty = tany;
1235 			sumark(&tr);
1236 			ecom(src, &tr, mod);
1237 			ind = mkunary(Oind, mkbin(Oadd, dupn(0, src, &tto), mkconst(src, IBY2WD)));
1238 			ind->ty = ind->left->ty = ind->left->right->ty = tint;
1239 			tr.op = Oas;
1240 			tr.left = ind;
1241 			tr.right = mkdeclname(src, d);
1242 			tr.ty = tr.right->ty = tint;
1243 			sumark(&tr);
1244 			tr.right->addable = mod->op == Oself && newfnptr ? Rnoff : Roff;
1245 			ecom(src, nil, &tr);
1246 			if(!sameaddr(&tto, nto))
1247 				genmove(src, Mas, n->ty, &tto, nto);
1248 			tfree(&tto);
1249 			break;
1250 		}
1251 		if(left->op == Oname && left->decl->store == Dtype){
1252 			genrawop(src, INEW, mktn(t), nil, nto);
1253 			break;
1254 		}
1255 		if(t->kind == Tadt && t->tags != nil){
1256 			pickdupcom(src, nto, left);
1257 			break;
1258 		}
1259 
1260 		tt = t;
1261 		if(left->op == Oconst && left->decl->store == Dtag)
1262 			t = left->decl->ty->tof;
1263 		/*
1264 		 * could eliminate temp if to does not occur
1265 		 * in tuple initializer
1266 		 */
1267 		talloc(&tto, n->ty, nto);
1268 		genrawop(src, INEW, mktn(t), nil, &tto);
1269 		tr.op = Oind;
1270 		tr.left = &tto;
1271 		tr.right = nil;
1272 		tr.ty = tt;
1273 		sumark(&tr);
1274 		ecom(src, &tr, left);
1275 		if(!sameaddr(&tto, nto))
1276 			genmove(src, Mas, n->ty, &tto, nto);
1277 		tfree(&tto);
1278 		break;
1279 	case Oload:
1280 		if(left->addable >= Rcant)
1281 			left = eacom(left, &tl, nto);
1282 		talloc(&tr, tint, nil);
1283 		if(LDT)
1284 			genrawop(src, ILOAD, left, right, nto);
1285 		else{
1286 			genrawop(src, ILEA, right, nil, &tr);
1287 			genrawop(src, ILOAD, left, &tr, nto);
1288 		}
1289 		tfree(&tl);
1290 		tfree(&tr);
1291 		break;
1292 	case Ocast:
1293 		if(left->addable >= Rcant)
1294 			left = eacom(left, &tl, nto);
1295 		t = left->ty;
1296 		if(t->kind == Tfix || n->ty->kind == Tfix){
1297 			op = casttab[t->kind][n->ty->kind];
1298 			if(op == ICVTXX)
1299 				genfixcastop(src, op, left, nto);
1300 			else{
1301 				tn = sumark(mkrconst(src, scale2(t, n->ty)));
1302 				genrawop(src, op, left, tn, nto);
1303 			}
1304 		}
1305 		else
1306 			genrawop(src, casttab[t->kind][n->ty->kind], left, nil, nto);
1307 		tfree(&tl);
1308 		break;
1309 	case Oarray:
1310 		if(left->addable >= Rcant)
1311 			left = eacom(left, &tl, nto);
1312 		genrawop(esrc(src, &left->src, nto), arrayz ? INEWAZ : INEWA, left, mktn(n->ty->tof), nto);
1313 		if(right != nil)
1314 			arraycom(nto, right);
1315 		tfree(&tl);
1316 		break;
1317 	case Oslice:
1318 		tn = right->right;
1319 		right = right->left;
1320 
1321 		/*
1322 		 * make the left node of the slice directly addressable
1323 		 * therefore, if it's len is taken (via tn),
1324 		 * left's tree won't be rewritten
1325 		 */
1326 		if(left->addable >= Rcant)
1327 			left = eacom(left, &tl, nil);
1328 
1329 		if(tn->op == Onothing){
1330 			tn = mkn(Olen, left, nil);
1331 			tn->src = *src;
1332 			tn->ty = tint;
1333 			sumark(tn);
1334 		}
1335 		if(tn->addable < Ralways){
1336 			if(right->addable >= Rcant)
1337 				right = eacom(right, &tr, nil);
1338 		}else if(right->temps <= tn->temps){
1339 			tn = ecom(&tn->src, talloc(&ttn, tn->ty, nil), tn);
1340 			if(right->addable >= Rcant)
1341 				right = eacom(right, &tr, nil);
1342 		}else{
1343 			right = eacom(right, &tr, nil);
1344 			tn = ecom(&tn->src, talloc(&ttn, tn->ty, nil), tn);
1345 		}
1346 		op = ISLICEA;
1347 		if(nto->ty == tstring)
1348 			op = ISLICEC;
1349 
1350 		/*
1351 		 * overwrite the destination last,
1352 		 * since it might be used in computing the slice bounds
1353 		 */
1354 		if(!sameaddr(left, nto))
1355 			ecom(&left->src, nto, left);
1356 
1357 		genrawop(src, op, right, tn, nto);
1358 		tfree(&tl);
1359 		tfree(&tr);
1360 		tfree(&ttn);
1361 		break;
1362 	case Oindx:
1363 		if(right->addable < Rcant){
1364 			if(left->addable >= Rcant)
1365 				left = eacom(left, &tl, nto);
1366 		}else if(left->temps < right->temps){
1367 			right = eacom(right, &tr, nto);
1368 			if(left->addable >= Rcant)
1369 				left = eacom(left, &tl, nil);
1370 		}else{
1371 			left = eacom(left, &tl, nto);
1372 			right = eacom(right, &tr, nil);
1373 		}
1374 		if(nto->addable >= Ralways)
1375 			nto = ecom(src, talloc(&tto, nto->ty, nil), nto);
1376 		op = IINDX;
1377 		switch(left->ty->tof->size){
1378 		case IBY2LG:
1379 			op = IINDL;
1380 			if(left->ty->tof == treal)
1381 				op = IINDF;
1382 			break;
1383 		case IBY2WD:
1384 			op = IINDW;
1385 			break;
1386 		case 1:
1387 			op = IINDB;
1388 			break;
1389 		}
1390 		genrawop(src, op, left, nto, right);
1391 		// array[] of {....} [index] frees array too early (before index value used)
1392 		// function(...) [index] frees array too early (before index value used)
1393 		if(tl.decl != nil)
1394 			tfreelater(&tl);
1395 		else
1396 			tfree(&tl);
1397 		tfree(&tr);
1398 		tfree(&tto);
1399 		break;
1400 	case Oind:
1401 		n = eacom(n, &tl, nto);
1402 		genmove(src, Mas, n->ty, n, nto);
1403 		tfree(&tl);
1404 		break;
1405 	case Onot:
1406 	case Oandand:
1407 	case Ooror:
1408 	case Oeq:
1409 	case Oneq:
1410 	case Olt:
1411 	case Oleq:
1412 	case Ogt:
1413 	case Ogeq:
1414 		p = bcom(n, 1, nil);
1415 		genmove(src, Mas, tint, sumark(mkconst(src, 1)), nto);
1416 		pp = genrawop(src, IJMP, nil, nil, nil);
1417 		patch(p, nextinst());
1418 		genmove(src, Mas, tint, sumark(mkconst(src, 0)), nto);
1419 		patch(pp, nextinst());
1420 		break;
1421 	case Oself:
1422 		if(newfnptr){
1423 			if(nto != nil)
1424 				genrawop(src, ISELF, nil, nil, nto);
1425 			break;
1426 		}
1427 		tn = sumark(mkdeclname(src, selfdecl));
1428 		p = genbra(src, Oneq, tn, sumark(mkdeclname(src, nildecl)));
1429 		n->op = Oload;
1430 		ecom(src, tn, n);
1431 		patch(p, nextinst());
1432 		genmove(src, Mas, n->ty, tn, nto);
1433 		break;
1434 	}
1435 	return nto;
1436 }
1437 
1438 /*
1439  * compile exp n to yield an addressable expression
1440  * use reg to build a temporary; if t is a temp, it is usable
1441  * if dangle leaves the address dangling, generate into a temporary
1442  *	this should only happen with arrays
1443  *
1444  * note that 0adr's are strange as they are only used
1445  * for calculating the addresses of fields within adt's.
1446  * therefore an Oind is the parent or grandparent of the Oadr,
1447  * and we pick off all of the cases where Oadr's argument is not
1448  * addressable by looking from the Oind.
1449  */
1450 Node*
1451 eacom(Node *n, Node *reg, Node *t)
1452 {
1453 	Node *left, *tn;
1454 
1455 	if(n->op == Ocomma){
1456 		tn = n->left->left;
1457 		ecom(&n->left->src, nil, n->left);
1458 		n = eacom(n->right, reg, t);
1459 		tfree(tn);
1460 		return n;
1461 	}
1462 
1463 	if(debug['e'] || debug['E'])
1464 		print("eacom: %n\n", n);
1465 
1466 	left = n->left;
1467 	if(n->op != Oind){
1468 		ecom(&n->src, talloc(reg, n->ty, t), n);
1469 		reg->src = n->src;
1470 		return reg;
1471 	}
1472 
1473 	if(left->op == Oadd && left->right->op == Oconst){
1474 		if(left->left->op == Oadr){
1475 			left->left->left = eacom(left->left->left, reg, t);
1476 			sumark(n);
1477 			if(n->addable >= Rcant)
1478 				fatal("eacom can't make node addressable: %n", n);
1479 			return n;
1480 		}
1481 		talloc(reg, left->left->ty, t);
1482 		ecom(&left->left->src, reg, left->left);
1483 		left->left->decl = reg->decl;
1484 		left->left->addable = Rreg;
1485 		left->left = reg;
1486 		left->addable = Raadr;
1487 		n->addable = Radr;
1488 	}else if(left->op == Oadr){
1489 		talloc(reg, left->left->ty, t);
1490 		ecom(&left->left->src, reg, left->left);
1491 
1492 		/*
1493 		 * sleaze: treat the temp as the type of the field, not the enclosing structure
1494 		 */
1495 		reg->ty = n->ty;
1496 		reg->src = n->src;
1497 		return reg;
1498 	}else{
1499 		talloc(reg, left->ty, t);
1500 		ecom(&left->src, reg, left);
1501 		n->left = reg;
1502 		n->addable = Radr;
1503 	}
1504 	return n;
1505 }
1506 
1507 /*
1508  * compile an assignment to an array slice
1509  */
1510 Node*
1511 slicelcom(Src *src, Node *nto, Node *n)
1512 {
1513 	Node *left, *right, *v;
1514 	Node tl, tr, tv, tu;
1515 
1516 	tl.decl = nil;
1517 	tr.decl = nil;
1518 	tv.decl = nil;
1519 	tu.decl = nil;
1520 
1521 	left = n->left->left;
1522 	right = n->left->right->left;
1523 	v = n->right;
1524 	if(right->addable < Ralways){
1525 		if(left->addable >= Rcant)
1526 			left = eacom(left, &tl, nto);
1527 	}else if(left->temps <= right->temps){
1528 		right = ecom(&right->src, talloc(&tr, right->ty, nto), right);
1529 		if(left->addable >= Rcant)
1530 			left = eacom(left, &tl, nil);
1531 	}else{
1532 		left = eacom(left, &tl, nil);		/* dangle on right and v */
1533 		right = ecom(&right->src, talloc(&tr, right->ty, nil), right);
1534 	}
1535 
1536 	switch(n->op){
1537 	case Oas:
1538 		if(v->addable >= Rcant)
1539 			v = eacom(v, &tv, nil);
1540 		break;
1541 	}
1542 
1543 	genrawop(&n->src, ISLICELA, v, right, left);
1544 	if(nto != nil)
1545 		genmove(src, Mas, n->ty, left, nto);
1546 	tfree(&tl);
1547 	tfree(&tv);
1548 	tfree(&tr);
1549 	tfree(&tu);
1550 	return nto;
1551 }
1552 
1553 /*
1554  * compile an assignment to a string location
1555  */
1556 Node*
1557 indsascom(Src *src, Node *nto, Node *n)
1558 {
1559 	Node *left, *right, *u, *v;
1560 	Node tl, tr, tv, tu;
1561 
1562 	tl.decl = nil;
1563 	tr.decl = nil;
1564 	tv.decl = nil;
1565 	tu.decl = nil;
1566 
1567 	left = n->left->left;
1568 	right = n->left->right;
1569 	v = n->right;
1570 	if(right->addable < Ralways){
1571 		if(left->addable >= Rcant)
1572 			left = eacom(left, &tl, nto);
1573 	}else if(left->temps <= right->temps){
1574 		right = ecom(&right->src, talloc(&tr, right->ty, nto), right);
1575 		if(left->addable >= Rcant)
1576 			left = eacom(left, &tl, nil);
1577 	}else{
1578 		left = eacom(left, &tl, nil);		/* dangle on right and v */
1579 		right = ecom(&right->src, talloc(&tr, right->ty, nil), right);
1580 	}
1581 
1582 	switch(n->op){
1583 	case Oas:
1584 		if(v->addable >= Rcant)
1585 			v = eacom(v, &tv, nil);
1586 		break;
1587 	case Oinc:
1588 	case Odec:
1589 		if(v->addable >= Rcant)
1590 			fatal("inc/dec amount not addable");
1591 		u = talloc(&tu, tint, nil);
1592 		genop(&n->left->src, Oinds, left, right, u);
1593 		if(nto != nil)
1594 			genmove(src, Mas, n->ty, u, nto);
1595 		nto = nil;
1596 		genop(&n->src, n->op, v, nil, u);
1597 		v = u;
1598 		break;
1599 	case Oaddas:
1600 	case Osubas:
1601 	case Omulas:
1602 	case Odivas:
1603 	case Omodas:
1604 	case Oexpas:
1605 	case Oandas:
1606 	case Ooras:
1607 	case Oxoras:
1608 	case Olshas:
1609 	case Orshas:
1610 		if(v->addable >= Rcant)
1611 			v = eacom(v, &tv, nil);
1612 		u = talloc(&tu, tint, nil);
1613 		genop(&n->left->src, Oinds, left, right, u);
1614 		genop(&n->src, n->op, v, nil, u);
1615 		v = u;
1616 		break;
1617 	}
1618 
1619 	genrawop(&n->src, IINSC, v, right, left);
1620 	tfree(&tl);
1621 	tfree(&tv);
1622 	tfree(&tr);
1623 	tfree(&tu);
1624 	if(nto != nil)
1625 		genmove(src, Mas, n->ty, v, nto);
1626 	return nto;
1627 }
1628 
1629 void
1630 callcom(Src *src, int op, Node *n, Node *ret)
1631 {
1632 	Node frame, tadd, toff, pass, *a, *mod, *ind, *nfn, *args, tmod, tind, *tn;
1633 	Inst *in,*p;
1634 	Decl *d, *callee;
1635 	long off;
1636 	int iop;
1637 
1638 	args = n->right;
1639 	nfn = n->left;
1640 	switch(nfn->op){
1641 		case Odot:
1642 			callee = nfn->right->decl;
1643 			nfn->addable = Rpc;
1644 			break;
1645 		case Omdot:
1646 			callee = nfn->right->decl;
1647 			break;
1648 		case Oname:
1649 			callee = nfn->decl;
1650 			break;
1651 		default:
1652 			callee = nil;
1653 			fatal("bad call op in callcom");
1654 	}
1655 	if(nfn->addable != Rpc && nfn->addable != Rmpc)
1656 		fatal("can't gen call addresses");
1657 	if(nfn->ty->tof != tnone && ret == nil){
1658 		ecom(src, talloc(&tmod, nfn->ty->tof, nil), n);
1659 		tfree(&tmod);
1660 		return;
1661 	}
1662 	if(ispoly(callee))
1663 		addfnptrs(callee, 0);
1664 	if(nfn->ty->varargs){
1665 		nfn->decl = dupdecl(nfn->right->decl);
1666 		nfn->decl->desc = gendesc(nfn->right->decl, idoffsets(nfn->ty->ids, MaxTemp, MaxAlign), nfn->ty->ids);
1667 	}
1668 
1669 	talloc(&frame, tint, nil);
1670 
1671 	mod = nfn->left;
1672 	ind = nfn->right;
1673 	tmod.decl = tind.decl = nil;
1674 	if(nfn->addable == Rmpc){
1675 		if(mod->addable >= Rcant)
1676 			mod = eacom(mod, &tmod, nil);		/* dangle always */
1677 		if(ind->op != Oname && ind->addable >= Ralways){
1678 			talloc(&tind, ind->ty, nil);
1679 			ecom(&ind->src, &tind, ind);
1680 			ind = &tind;
1681 		}
1682 		else if(ind->decl != nil && ind->decl->store != Darg)
1683 			ind->addable = Roff;
1684 	}
1685 
1686 	/*
1687 	 * stop nested uncalled frames
1688 	 * otherwise exception handling very complicated
1689 	 */
1690 	for(a = args; a != nil; a = a->right){
1691 		if(hascall(a->left)){
1692 			tn = mkn(0, nil, nil);
1693 			talloc(tn, a->left->ty, nil);
1694 			ecom(&a->left->src, tn, a->left);
1695 			a->left = tn;
1696 			tn->flags |= TEMP;
1697 		}
1698 	}
1699 
1700 	/*
1701 	 * allocate the frame
1702 	 */
1703 	if(nfn->addable == Rmpc && !nfn->ty->varargs){
1704 		genrawop(src, IMFRAME, mod, ind, &frame);
1705 	}else if(nfn->op == Odot){
1706 		genrawop(src, IFRAME, nfn->left, nil, &frame);
1707 	}else{
1708 		in = genrawop(src, IFRAME, nil, nil, &frame);
1709 		in->sm = Adesc;
1710 		in->s.decl = nfn->decl;
1711 	}
1712 
1713 	/*
1714 	 * build a fake node for the argument area
1715 	 */
1716 	toff = znode;
1717 	tadd = znode;
1718 	pass = znode;
1719 	toff.op = Oconst;
1720 	toff.addable = Rconst;
1721 	toff.ty = tint;
1722 	tadd.op = Oadd;
1723 	tadd.addable = Raadr;
1724 	tadd.left = &frame;
1725 	tadd.right = &toff;
1726 	tadd.ty = tint;
1727 	pass.op = Oind;
1728 	pass.addable = Radr;
1729 	pass.left = &tadd;
1730 
1731 	/*
1732 	 * compile all the args
1733 	 */
1734 	d = nfn->ty->ids;
1735 	off = 0;
1736 	for(a = args; a != nil; a = a->right){
1737 		off = d->offset;
1738 		toff.val = off;
1739 		if(d->ty->kind == Tpoly)
1740 			pass.ty = a->left->ty;
1741 		else
1742 			pass.ty = d->ty;
1743 		ecom(&a->left->src, &pass, a->left);
1744 		d = d->next;
1745 		if(a->left->flags & TEMP)
1746 			tfree(a->left);
1747 	}
1748 	if(off > maxstack)
1749 		maxstack = off;
1750 
1751 	/*
1752 	 * pass return value
1753 	 */
1754 	if(ret != nil){
1755 		toff.val = REGRET*IBY2WD;
1756 		pass.ty = nfn->ty->tof;
1757 		p = genrawop(src, ILEA, ret, nil, &pass);
1758 		p->m.offset = ret->ty->size;	/* for optimizer */
1759 	}
1760 
1761 	/*
1762 	 * call it
1763 	 */
1764 	if(nfn->addable == Rmpc){
1765 		iop = IMCALL;
1766 		if(op == Ospawn)
1767 			iop = IMSPAWN;
1768 		genrawop(src, iop, &frame, ind, mod);
1769 		tfree(&tmod);
1770 		tfree(&tind);
1771 	}else if(nfn->op == Odot){
1772 		iop = ICALL;
1773 		if(op == Ospawn)
1774 			iop = ISPAWN;
1775 		genrawop(src, iop, &frame, nil, nfn->right);
1776 	}else{
1777 		iop = ICALL;
1778 		if(op == Ospawn)
1779 			iop = ISPAWN;
1780 		in = genrawop(src, iop, &frame, nil, nil);
1781 		in->d.decl = nfn->decl;
1782 		in->dm = Apc;
1783 	}
1784 	tfree(&frame);
1785 }
1786 
1787 /*
1788  * initialization code for arrays
1789  * a must be addressable (< Rcant)
1790  */
1791 void
1792 arraycom(Node *a, Node *elems)
1793 {
1794 	Node tindex, fake, tmp, ri, *e, *n, *q, *body, *wild;
1795 	Inst *top, *out;
1796 	/* Case *c; */
1797 
1798 	if(debug['A'])
1799 		print("arraycom: %n %n\n", a, elems);
1800 
1801 	/* c = elems->ty->cse; */
1802 	/* don't use c->wild in case we've been inlined */
1803 	wild = nil;
1804 	for(e = elems; e != nil; e = e->right)
1805 		for(q = e->left->left; q != nil; q = q->right)
1806 			if(q->left->op == Owild)
1807 				wild = e->left;
1808 	if(wild != nil)
1809 		arraydefault(a, wild->right);
1810 
1811 	tindex = znode;
1812 	fake = znode;
1813 	talloc(&tmp, tint, nil);
1814 	tindex.op = Oindx;
1815 	tindex.addable = Rcant;
1816 	tindex.left = a;
1817 	tindex.right = nil;
1818 	tindex.ty = tint;
1819 	fake.op = Oind;
1820 	fake.addable = Radr;
1821 	fake.left = &tmp;
1822 	fake.ty = a->ty->tof;
1823 
1824 	for(e = elems; e != nil; e = e->right){
1825 		/*
1826 		 * just duplicate the initializer for Oor
1827 		 */
1828 		for(q = e->left->left; q != nil; q = q->right){
1829 			if(q->left->op == Owild)
1830 				continue;
1831 
1832 			body = e->left->right;
1833 			if(q->right != nil)
1834 				body = dupn(0, &nosrc, body);
1835 			top = nil;
1836 			out = nil;
1837 			ri.decl = nil;
1838 			if(q->left->op == Orange){
1839 				/*
1840 				 * for(i := q.left.left; i <= q.left.right; i++)
1841 				 */
1842 				talloc(&ri, tint, nil);
1843 				ri.src = q->left->src;
1844 				ecom(&q->left->src, &ri, q->left->left);
1845 
1846 				/* i <= q.left.right; */
1847 				n = mkn(Oleq, &ri, q->left->right);
1848 				n->src = q->left->src;
1849 				n->ty = tint;
1850 				top = nextinst();
1851 				out = bcom(n, 1, nil);
1852 
1853 				tindex.right = &ri;
1854 			}else{
1855 				tindex.right = q->left;
1856 			}
1857 
1858 			tindex.addable = Rcant;
1859 			tindex.src = q->left->src;
1860 			ecom(&tindex.src, &tmp, &tindex);
1861 
1862 			ecom(&body->src, &fake, body);
1863 
1864 			if(q->left->op == Orange){
1865 				/* i++ */
1866 				n = mkbin(Oinc, &ri, sumark(mkconst(&ri.src, 1)));
1867 				n->ty = tint;
1868 				n->addable = Rcant;
1869 				ecom(&n->src, nil, n);
1870 
1871 				/* jump to test */
1872 				patch(genrawop(&q->left->src, IJMP, nil, nil, nil), top);
1873 				patch(out, nextinst());
1874 				tfree(&ri);
1875 			}
1876 		}
1877 	}
1878 	tfree(&tmp);
1879 }
1880 
1881 /*
1882  * default initialization code for arrays.
1883  * compiles to
1884  *	n = len a;
1885  *	while(n){
1886  *		n--;
1887  *		a[n] = elem;
1888  *	}
1889  */
1890 void
1891 arraydefault(Node *a, Node *elem)
1892 {
1893 	Inst *out, *top;
1894 	Node n, e, *t;
1895 
1896 	if(debug['A'])
1897 		print("arraydefault: %n %n\n", a, elem);
1898 
1899 	t = mkn(Olen, a, nil);
1900 	t->src = elem->src;
1901 	t->ty = tint;
1902 	t->addable = Rcant;
1903 	talloc(&n, tint, nil);
1904 	n.src = elem->src;
1905 	ecom(&t->src, &n, t);
1906 
1907 	top = nextinst();
1908 	out = bcom(&n, 1, nil);
1909 
1910 	t = mkbin(Odec, &n, sumark(mkconst(&elem->src, 1)));
1911 	t->ty = tint;
1912 	t->addable = Rcant;
1913 	ecom(&t->src, nil, t);
1914 
1915 	e.decl = nil;
1916 	if(elem->addable >= Rcant)
1917 		elem = eacom(elem, &e, nil);
1918 
1919 	t = mkn(Oindx, a, &n);
1920 	t->src = elem->src;
1921 	t = mkbin(Oas, mkunary(Oind, t), elem);
1922 	t->ty = elem->ty;
1923 	t->left->ty = elem->ty;
1924 	t->left->left->ty = tint;
1925 	sumark(t);
1926 	ecom(&t->src, nil, t);
1927 
1928 	patch(genrawop(&t->src, IJMP, nil, nil, nil), top);
1929 
1930 	tfree(&n);
1931 	tfree(&e);
1932 	patch(out, nextinst());
1933 }
1934 
1935 void
1936 tupcom(Node *nto, Node *n)
1937 {
1938 	Node tadr, tadd, toff, fake, *e;
1939 	Decl *d;
1940 
1941 	if(debug['Y'])
1942 		print("tupcom %n\nto %n\n", n, nto);
1943 
1944 	/*
1945 	 * build a fake node for the tuple
1946 	 */
1947 	toff = znode;
1948 	tadd = znode;
1949 	fake = znode;
1950 	tadr = znode;
1951 	toff.op = Oconst;
1952 	toff.ty = tint;
1953 	tadr.op = Oadr;
1954 	tadr.left = nto;
1955 	tadr.ty = tint;
1956 	tadd.op = Oadd;
1957 	tadd.left = &tadr;
1958 	tadd.right = &toff;
1959 	tadd.ty = tint;
1960 	fake.op = Oind;
1961 	fake.left = &tadd;
1962 	sumark(&fake);
1963 	if(fake.addable >= Rcant)
1964 		fatal("tupcom: bad value exp %n", &fake);
1965 
1966 	/*
1967 	 * compile all the exps
1968 	 */
1969 	d = n->ty->ids;
1970 	for(e = n->left; e != nil; e = e->right){
1971 		toff.val = d->offset;
1972 		fake.ty = d->ty;
1973 		ecom(&e->left->src, &fake, e->left);
1974 		d = d->next;
1975 	}
1976 }
1977 
1978 void
1979 tuplcom(Node *n, Node *nto)
1980 {
1981 	Node tadr, tadd, toff, fake, tas, *e, *as;
1982 	Decl *d;
1983 
1984 	if(debug['Y'])
1985 		print("tuplcom %n\nto %n\n", n, nto);
1986 
1987 	/*
1988 	 * build a fake node for the tuple
1989 	 */
1990 	toff = znode;
1991 	tadd = znode;
1992 	fake = znode;
1993 	tadr = znode;
1994 	toff.op = Oconst;
1995 	toff.ty = tint;
1996 	tadr.op = Oadr;
1997 	tadr.left = n;
1998 	tadr.ty = tint;
1999 	tadd.op = Oadd;
2000 	tadd.left = &tadr;
2001 	tadd.right = &toff;
2002 	tadd.ty = tint;
2003 	fake.op = Oind;
2004 	fake.left = &tadd;
2005 	sumark(&fake);
2006 	if(fake.addable >= Rcant)
2007 		fatal("tuplcom: bad value exp for %n", &fake);
2008 
2009 	/*
2010 	 * compile all the exps
2011 	 */
2012 	d = nto->ty->ids;
2013 	if(nto->ty->kind == Tadtpick)
2014 		d = nto->ty->tof->ids->next;
2015 	for(e = nto->left; e != nil; e = e->right){
2016 		as = e->left;
2017 		if(as->op != Oname || as->decl != nildecl){
2018 			toff.val = d->offset;
2019 			fake.ty = d->ty;
2020 			fake.src = as->src;
2021 			if(as->addable < Rcant)
2022 				genmove(&as->src, Mas, d->ty, &fake, as);
2023 			else{
2024 				tas.op = Oas;
2025 				tas.ty = d->ty;
2026 				tas.src = as->src;
2027 				tas.left = as;
2028 				tas.right = &fake;
2029 				tas.addable = Rcant;
2030 				ecom(&tas.src, nil, &tas);
2031 			}
2032 		}
2033 		d = d->next;
2034 	}
2035 }
2036 
2037 void
2038 tuplrcom(Node *n, Node *nto)
2039 {
2040 	Node *s, *d, tas;
2041 	Decl *de;
2042 
2043 	de = nto->ty->ids;
2044 	for(s = n->left, d = nto->left; s != nil && d != nil; s = s->right, d = d->right){
2045 		if(d->left->op != Oname || d->left->decl != nildecl){
2046 			tas.op = Oas;
2047 			tas.ty = de->ty;
2048 			tas.src = s->left->src;
2049 			tas.left = d->left;
2050 			tas.right = s->left;
2051 			sumark(&tas);
2052 			ecom(&tas.src, nil, &tas);
2053 		}
2054 		de = de->next;
2055 	}
2056 	if(s != nil || d != nil)
2057 		fatal("tuplrcom");
2058 }
2059 
2060 /*
2061  * boolean compiler
2062  * fall through when condition == true
2063  */
2064 Inst*
2065 bcom(Node *n, int iftrue, Inst *b)
2066 {
2067 	Inst *bb;
2068 	Node tl, tr, *t, *left, *right, *tn;
2069 	int op;
2070 
2071 	if(n->op == Ocomma){
2072 		tn = n->left->left;
2073 		ecom(&n->left->src, nil, n->left);
2074 		bb = bcom(n->right, iftrue, b);
2075 		tfree(tn);
2076 		return bb;
2077 	}
2078 
2079 	if(debug['b'])
2080 		print("bcom %n %d\n", n, iftrue);
2081 
2082 	left = n->left;
2083 	right = n->right;
2084 	op = n->op;
2085 
2086 	switch(op){
2087 	case Onothing:
2088 		return b;
2089 	case Onot:
2090 		return bcom(n->left, !iftrue, b);
2091 	case Oandand:
2092 		if(!iftrue)
2093 			return oror(n, iftrue, b);
2094 		return andand(n, iftrue, b);
2095 	case Ooror:
2096 		if(!iftrue)
2097 			return andand(n, iftrue, b);
2098 		return oror(n, iftrue, b);
2099 	case Ogt:
2100 	case Ogeq:
2101 	case Oneq:
2102 	case Oeq:
2103 	case Olt:
2104 	case Oleq:
2105 		break;
2106 	default:
2107 		if(n->ty->kind == Tint){
2108 			right = mkconst(&n->src, 0);
2109 			right->addable = Rconst;
2110 			left = n;
2111 			op = Oneq;
2112 			break;
2113 		}
2114 		fatal("can't bcom %n", n);
2115 		return b;
2116 	}
2117 
2118 	if(iftrue)
2119 		op = oprelinvert[op];
2120 
2121 	if(left->addable < right->addable){
2122 		t = left;
2123 		left = right;
2124 		right = t;
2125 		op = opcommute[op];
2126 	}
2127 
2128 	tl.decl = nil;
2129 	tr.decl = nil;
2130 	if(right->addable < Ralways){
2131 		if(left->addable >= Rcant)
2132 			left = eacom(left, &tl, nil);
2133 	}else if(left->temps <= right->temps){
2134 		right = ecom(&right->src, talloc(&tr, right->ty, nil), right);
2135 		if(left->addable >= Rcant)
2136 			left = eacom(left, &tl, nil);
2137 	}else{
2138 		left = eacom(left, &tl, nil);
2139 		right = ecom(&right->src, talloc(&tr, right->ty, nil), right);
2140 	}
2141 	bb = genbra(&n->src, op, left, right);
2142 	bb->branch = b;
2143 	tfree(&tl);
2144 	tfree(&tr);
2145 	return bb;
2146 }
2147 
2148 Inst*
2149 andand(Node *n, int iftrue, Inst *b)
2150 {
2151 	if(debug['b'])
2152 		print("andand %n\n", n);
2153 	b = bcom(n->left, iftrue, b);
2154 	b = bcom(n->right, iftrue, b);
2155 	return b;
2156 }
2157 
2158 Inst*
2159 oror(Node *n, int iftrue, Inst *b)
2160 {
2161 	Inst *bb;
2162 
2163 	if(debug['b'])
2164 		print("oror %n\n", n);
2165 	bb = bcom(n->left, !iftrue, nil);
2166 	b = bcom(n->right, iftrue, b);
2167 	patch(bb, nextinst());
2168 	return b;
2169 }
2170 
2171 /*
2172  * generate code for a recva expression
2173  * this is just a hacked up small alt
2174  */
2175 void
2176 recvacom(Src *src, Node *nto, Node *n)
2177 {
2178 	Label *labs;
2179 	Case *c;
2180 	Node which, tab, off, add, adr, slot, *left;
2181 	Type *talt;
2182 	Inst *p;
2183 
2184 	left = n->left;
2185 
2186 	labs = allocmem(1 * sizeof *labs);
2187 	labs[0].isptr = left->addable >= Rcant;
2188 	c = allocmem(sizeof *c);
2189 	c->nlab = 1;
2190 	c->labs = labs;
2191 	talt = mktalt(c);
2192 
2193 	talloc(&which, tint, nil);
2194 	talloc(&tab, talt, nil);
2195 
2196 	/*
2197 	 * build the node for the address of each channel,
2198 	 * the values to send, and the storage fro values received
2199 	 */
2200 	off = znode;
2201 	off.op = Oconst;
2202 	off.ty = tint;
2203 	off.addable = Rconst;
2204 	adr = znode;
2205 	adr.op = Oadr;
2206 	adr.left = &tab;
2207 	adr.ty = tint;
2208 	add = znode;
2209 	add.op = Oadd;
2210 	add.left = &adr;
2211 	add.right = &off;
2212 	add.ty = tint;
2213 	slot = znode;
2214 	slot.op = Oind;
2215 	slot.left = &add;
2216 	sumark(&slot);
2217 
2218 	/*
2219 	 * gen the channel
2220 	 * this sleaze is lying to the garbage collector
2221 	 */
2222 	off.val = 2*IBY2WD;
2223 	if(left->addable < Rcant)
2224 		genmove(src, Mas, tint, left, &slot);
2225 	else{
2226 		slot.ty = left->ty;
2227 		ecom(src, &slot, left);
2228 		slot.ty = nil;
2229 	}
2230 
2231 	/*
2232 	 * gen the value
2233 	 */
2234 	off.val += IBY2WD;
2235 	p = genrawop(&left->src, ILEA, nto, nil, &slot);
2236 	p->m.offset = nto->ty->size;	/* for optimizer */
2237 
2238 	/*
2239 	 * number of senders and receivers
2240 	 */
2241 	off.val = 0;
2242 	genmove(src, Mas, tint, sumark(mkconst(src, 0)), &slot);
2243 	off.val += IBY2WD;
2244 	genmove(src, Mas, tint, sumark(mkconst(src, 1)), &slot);
2245 	off.val += IBY2WD;
2246 
2247 	p = genrawop(src, IALT, &tab, nil, &which);
2248 	p->m.offset = talt->size;	/* for optimizer */
2249 	tfree(&which);
2250 	tfree(&tab);
2251 }
2252 
2253 /*
2254  * generate code to duplicate an adt with pick fields
2255  * this is just a hacked up small pick
2256  * n is Oind(exp)
2257  */
2258 void
2259 pickdupcom(Src *src, Node *nto, Node *n)
2260 {
2261 	Node *start, *stop, *node, *orig, *dest, tmp, clab;
2262 	Case *c;
2263 	Inst *j, *jmps, *wild;
2264 	Label *labs;
2265 	Decl *d, *tg, *stg;
2266 	Type *t;
2267 	int i, nlab;
2268 	char buf[32];
2269 
2270 	if(n->op != Oind)
2271 		fatal("pickdupcom not Oind: %n" ,n);
2272 
2273 	t = n->ty;
2274 	nlab = t->decl->tag;
2275 
2276 	/*
2277 	 * generate global which has case labels
2278 	 */
2279 	seprint(buf, buf+sizeof(buf), ".c%d", nlabel++);
2280 	d = mkids(src, enter(buf, 0), mktype(&src->start, &src->stop, Tcase, nil, nil), nil);
2281 	d->init = mkdeclname(src, d);
2282 
2283 	clab.addable = Rmreg;
2284 	clab.left = nil;
2285 	clab.right = nil;
2286 	clab.op = Oname;
2287 	clab.ty = d->ty;
2288 	clab.decl = d;
2289 
2290 	/*
2291 	 * generate a temp to hold the real value
2292 	 * then generate a case on the tag
2293 	 */
2294 	orig = n->left;
2295 	talloc(&tmp, orig->ty, nil);
2296 	ecom(src, &tmp, orig);
2297 	orig = mkunary(Oind, &tmp);
2298 	orig->ty = tint;
2299 	sumark(orig);
2300 
2301 	dest = mkunary(Oind, nto);
2302 	dest->ty = nto->ty->tof;
2303 	sumark(dest);
2304 
2305 	genrawop(src, ICASE, orig, nil, &clab);
2306 
2307 	labs = allocmem(nlab * sizeof *labs);
2308 
2309 	i = 0;
2310 	jmps = nil;
2311 	for(tg = t->tags; tg != nil; tg = tg->next){
2312 		stg = tg;
2313 		for(; tg->next != nil; tg = tg->next)
2314 			if(stg->ty != tg->next->ty)
2315 				break;
2316 		start = sumark(simplify(mkdeclname(src, stg)));
2317 		stop = start;
2318 		node = start;
2319 		if(stg != tg){
2320 			stop = sumark(simplify(mkdeclname(src, tg)));
2321 			node = mkbin(Orange, start, stop);
2322 		}
2323 
2324 		labs[i].start = start;
2325 		labs[i].stop = stop;
2326 		labs[i].node = node;
2327 		labs[i++].inst = nextinst();
2328 
2329 		genrawop(src, INEW, mktn(tg->ty->tof), nil, nto);
2330 		genmove(src, Mas, tg->ty->tof, orig, dest);
2331 
2332 		j = genrawop(src, IJMP, nil, nil, nil);
2333 		j->branch = jmps;
2334 		jmps = j;
2335 	}
2336 
2337 	/*
2338 	 * this should really be a runtime error
2339 	 */
2340 	wild = genrawop(src, IJMP, nil, nil, nil);
2341 	patch(wild, wild);
2342 
2343 	patch(jmps, nextinst());
2344 	tfree(&tmp);
2345 
2346 	if(i > nlab)
2347 		fatal("overflowed label tab for pickdupcom");
2348 
2349 	c = allocmem(sizeof *c);
2350 	c->nlab = i;
2351 	c->nsnd = 0;
2352 	c->labs = labs;
2353 	c->iwild = wild;
2354 
2355 	d->ty->cse = c;
2356 	usetype(d->ty);
2357 	installids(Dglobal, d);
2358 }
2359 
2360 /*
2361  * see if name n occurs anywhere in e
2362  */
2363 int
2364 tupaliased(Node *n, Node *e)
2365 {
2366 	for(;;){
2367 		if(e == nil)
2368 			return 0;
2369 		if(e->op == Oname && e->decl == n->decl)
2370 			return 1;
2371 		if(tupaliased(n, e->left))
2372 			return 1;
2373 		e = e->right;
2374 	}
2375 }
2376 
2377 /*
2378  * see if any name in n occurs anywere in e
2379  */
2380 int
2381 tupsaliased(Node *n, Node *e)
2382 {
2383 	for(;;){
2384 		if(n == nil)
2385 			return 0;
2386 		if(n->op == Oname && tupaliased(n, e))
2387 			return 1;
2388 		if(tupsaliased(n->left, e))
2389 			return 1;
2390 		n = n->right;
2391 	}
2392 }
2393 
2394 /*
2395  * put unaddressable constants in the global data area
2396  */
2397 Decl*
2398 globalconst(Node *n)
2399 {
2400 	Decl *d;
2401 	Sym *s;
2402 	char buf[32];
2403 
2404 	seprint(buf, buf+sizeof(buf), ".i.%.8lux", (long)n->val);
2405 	s = enter(buf, 0);
2406 	d = s->decl;
2407 	if(d == nil){
2408 		d = mkids(&n->src, s, tint, nil);
2409 		installids(Dglobal, d);
2410 		d->init = n;
2411 		d->refs++;
2412 	}
2413 	return d;
2414 }
2415 
2416 Decl*
2417 globalBconst(Node *n)
2418 {
2419 	Decl *d;
2420 	Sym *s;
2421 	char buf[32];
2422 
2423 	seprint(buf, buf+sizeof(buf), ".B.%.8lux.%8lux", (long)(n->val>>32), (long)n->val);
2424 
2425 	s = enter(buf, 0);
2426 	d = s->decl;
2427 	if(d == nil){
2428 		d = mkids(&n->src, s, tbig, nil);
2429 		installids(Dglobal, d);
2430 		d->init = n;
2431 		d->refs++;
2432 	}
2433 	return d;
2434 }
2435 
2436 Decl*
2437 globalbconst(Node *n)
2438 {
2439 	Decl *d;
2440 	Sym *s;
2441 	char buf[32];
2442 
2443 	seprint(buf, buf+sizeof(buf), ".b.%.2lux", (long)n->val & 0xff);
2444 	s = enter(buf, 0);
2445 	d = s->decl;
2446 	if(d == nil){
2447 		d = mkids(&n->src, s, tbyte, nil);
2448 		installids(Dglobal, d);
2449 		d->init = n;
2450 		d->refs++;
2451 	}
2452 	return d;
2453 }
2454 
2455 Decl*
2456 globalfconst(Node *n)
2457 {
2458 	Decl *d;
2459 	Sym *s;
2460 	char buf[32];
2461 	ulong dv[2];
2462 
2463 	dtocanon(n->rval, dv);
2464 	seprint(buf, buf+sizeof(buf), ".f.%.8lux.%8lux", dv[0], dv[1]);
2465 	s = enter(buf, 0);
2466 	d = s->decl;
2467 	if(d == nil){
2468 		d = mkids(&n->src, s, treal, nil);
2469 		installids(Dglobal, d);
2470 		d->init = n;
2471 		d->refs++;
2472 	}
2473 	return d;
2474 }
2475 
2476 Decl*
2477 globalsconst(Node *n)
2478 {
2479 	Decl *d;
2480 	Sym *s;
2481 
2482 	s = n->decl->sym;
2483 	d = s->decl;
2484 	if(d == nil){
2485 		d = mkids(&n->src, s, tstring, nil);
2486 		installids(Dglobal, d);
2487 		d->init = n;
2488 	}
2489 	d->refs++;
2490 	return d;
2491 }
2492 
2493 static Node*
2494 subst(Decl *d, Node *e, Node *n)
2495 {
2496 	if(n == nil)
2497 		return nil;
2498 	if(n->op == Oname){
2499 		if(d == n->decl){
2500 			n = dupn(0, nil, e);
2501 			n->ty = d->ty;
2502 		}
2503 		return n;
2504 	}
2505 	n->left = subst(d, e, n->left);
2506 	n->right = subst(d, e, n->right);
2507 	return n;
2508 }
2509 
2510 static Node*
2511 putinline(Node *n)
2512 {
2513 	Node *e, *tn;
2514 	Type *t;
2515 	Decl *d;
2516 
2517 if(debug['z']) print("inline1: %n\n", n);
2518 	if(n->left->op == Oname)
2519 		d = n->left->decl;
2520 	else
2521 		d = n->left->right->decl;
2522 	e = d->init;
2523 	t = e->ty;
2524 	e = dupn(1, &n->src, e->right->left->left);
2525 	for(d = t->ids, n = n->right; d != nil && n != nil; d = d->next, n = n->right){
2526 		if(hasside(n->left, 0) && occurs(d, e) != 1){
2527 			tn = talloc(mkn(0, nil, nil), d->ty, nil);
2528 			e = mkbin(Ocomma, mkbin(Oas, tn, n->left), subst(d, tn, e));
2529 			e->ty = e->right->ty;
2530 			e->left->ty = d->ty;
2531 		}
2532 		else
2533 			e = subst(d, n->left, e);
2534 	}
2535 	if(d != nil || n != nil)
2536 		fatal("bad arg match in putinline()");
2537 if(debug['z']) print("inline2: %n\n", e);
2538 	return e;
2539 }
2540 
2541 static void
2542 fpcall(Src *src, int op, Node *n, Node *ret)
2543 {
2544 	Node tp, *e, *mod, *ind;
2545 
2546 	tp.decl = nil;
2547 	e = n->left->left;
2548 	if(e->addable >= Rcant)
2549 		e = eacom(e, &tp, nil);
2550 	mod = mkunary(Oind, e);
2551 	ind = mkunary(Oind, mkbin(Oadd, dupn(0, src, e), mkconst(src, IBY2WD)));
2552 	n->left = mkbin(Omdot, mod, ind);
2553 	n->left->ty = e->ty->tof;
2554 	mod->ty = ind->ty = ind->left->ty = ind->left->right->ty = tint;
2555 	sumark(n);
2556 	callcom(src, op, n, ret);
2557 	tfree(&tp);
2558 }
2559