Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "gc.h"
2
 
3
void
4
cgen(Node *n, Node *nn)
5
{
6
	Node *l, *r;
7
	Prog *p1;
8
	Node nod, nod1, nod2, nod3, nod4;
9
	int o;
10
	long v, curs;
11
 
12
	if(debug['g']) {
13
		prtree(nn, "cgen lhs");
14
		prtree(n, "cgen");
15
	}
16
	if(n == Z || n->type == T)
17
		return;
18
	if(typesuv[n->type->etype]) {
19
		sugen(n, nn, n->type->width);
20
		return;
21
	}
22
	l = n->left;
23
	r = n->right;
24
	o = n->op;
25
	if(n->addable >= INDEXED) {
26
		if(nn == Z) {
27
			switch(o) {
28
			default:
29
				nullwarn(Z, Z);
30
				break;
31
			case OINDEX:
32
				nullwarn(l, r);
33
				break;
34
			}
35
			return;
36
		}
37
		gmove(n, nn);
38
		return;
39
	}
40
	curs = cursafe;
41
 
42
	if(n->complex >= FNX)
43
	if(l->complex >= FNX)
44
	if(r != Z && r->complex >= FNX)
45
	switch(o) {
46
	default:
47
		regret(&nod, r);
48
		cgen(r, &nod);
49
 
50
		regsalloc(&nod1, r);
51
		gopcode(OAS, &nod, Z, &nod1);
52
 
53
		regfree(&nod);
54
		nod = *n;
55
		nod.right = &nod1;
56
		cgen(&nod, nn);
57
		return;
58
 
59
	case OFUNC:
60
	case OCOMMA:
61
	case OANDAND:
62
	case OOROR:
63
	case OCOND:
64
	case ODOT:
65
		break;
66
	}
67
 
68
	switch(o) {
69
	default:
70
		diag(n, "unknown op in cgen: %O", o);
71
		break;
72
 
73
	case OAS:
74
		if(l->op == OBIT)
75
			goto bitas;
76
		if(l->addable >= INDEXED && l->complex < FNX) {
77
			if(nn != Z || r->addable < INDEXED) {
78
				if(r->complex >= FNX && nn == Z)
79
					regret(&nod, r);
80
				else
81
					regalloc(&nod, r, nn);
82
				cgen(r, &nod);
83
				gmove(&nod, l);
84
				if(nn != Z)
85
					gmove(&nod, nn);
86
				regfree(&nod);
87
			} else
88
				gmove(r, l);
89
			break;
90
		}
91
		if(l->complex >= r->complex) {
92
			reglcgen(&nod1, l, Z);
93
			if(r->addable >= INDEXED) {
94
				gmove(r, &nod1);
95
				if(nn != Z)
96
					gmove(r, nn);
97
				regfree(&nod1);
98
				break;
99
			}
100
			regalloc(&nod, r, nn);
101
			cgen(r, &nod);
102
		} else {
103
			regalloc(&nod, r, nn);
104
			cgen(r, &nod);
105
			reglcgen(&nod1, l, Z);
106
		}
107
		gmove(&nod, &nod1);
108
		regfree(&nod);
109
		regfree(&nod1);
110
		break;
111
 
112
	bitas:
113
		n = l->left;
114
		regalloc(&nod, r, nn);
115
		if(l->complex >= r->complex) {
116
			reglcgen(&nod1, n, Z);
117
			cgen(r, &nod);
118
		} else {
119
			cgen(r, &nod);
120
			reglcgen(&nod1, n, Z);
121
		}
122
		regalloc(&nod2, n, Z);
123
		gopcode(OAS, &nod1, Z, &nod2);
124
		bitstore(l, &nod, &nod1, &nod2, nn);
125
		break;
126
 
127
	case OBIT:
128
		if(nn == Z) {
129
			nullwarn(l, Z);
130
			break;
131
		}
132
		bitload(n, &nod, Z, Z, nn);
133
		gopcode(OAS, &nod, Z, nn);
134
		regfree(&nod);
135
		break;
136
 
137
	case OADD:
138
	case OSUB:
139
	case OAND:
140
	case OOR:
141
	case OXOR:
142
	case OLSHR:
143
	case OASHL:
144
	case OASHR:
145
		/*
146
		 * immediate operands
147
		 */
148
		if(nn != Z)
149
		if(r->op == OCONST)
150
		if(!typefd[n->type->etype]) {
151
			cgen(l, nn);
152
			if(r->vconst == 0)
153
			if(o != OAND)
154
				break;
155
			if(nn != Z)
156
				gopcode(o, r, Z, nn);
157
			break;
158
		}
159
 
160
	case OLMUL:
161
	case OLDIV:
162
	case OLMOD:
163
	case OMUL:
164
	case ODIV:
165
	case OMOD:
166
		if(nn == Z) {
167
			nullwarn(l, r);
168
			break;
169
		}
170
		if(o == OMUL || o == OLMUL) {
171
			if(mulcon(n, nn))
172
				break;
173
		}
174
		if(l->complex >= r->complex) {
175
			regalloc(&nod, l, nn);
176
			cgen(l, &nod);
177
			regalloc(&nod1, r, Z);
178
			cgen(r, &nod1);
179
			gopcode(o, &nod1, Z, &nod);
180
		} else {
181
			regalloc(&nod, r, nn);
182
			cgen(r, &nod);
183
			regalloc(&nod1, l, Z);
184
			cgen(l, &nod1);
185
			gopcode(o, &nod, &nod1, &nod);
186
		}
187
		gopcode(OAS, &nod, Z, nn);
188
		regfree(&nod);
189
		regfree(&nod1);
190
		break;
191
 
192
	case OASLSHR:
193
	case OASASHL:
194
	case OASASHR:
195
	case OASAND:
196
	case OASADD:
197
	case OASSUB:
198
	case OASXOR:
199
	case OASOR:
200
		if(l->op == OBIT)
201
			goto asbitop;
202
		if(r->op == OCONST)
203
		if(!typefd[r->type->etype])
204
		if(!typefd[n->type->etype]) {
205
			if(l->addable < INDEXED)
206
				reglcgen(&nod2, l, Z);
207
			else
208
				nod2 = *l;
209
			regalloc(&nod, r, nn);
210
			gopcode(OAS, &nod2, Z, &nod);
211
			gopcode(o, r, Z, &nod);
212
			gopcode(OAS, &nod, Z, &nod2);
213
 
214
			regfree(&nod);
215
			if(l->addable < INDEXED)
216
				regfree(&nod2);
217
			break;
218
		}
219
 
220
	case OASLMUL:
221
	case OASLDIV:
222
	case OASLMOD:
223
	case OASMUL:
224
	case OASDIV:
225
	case OASMOD:
226
		if(l->op == OBIT)
227
			goto asbitop;
228
		if(l->complex >= r->complex) {
229
			if(l->addable < INDEXED)
230
				reglcgen(&nod2, l, Z);
231
			else
232
				nod2 = *l;
233
			regalloc(&nod1, r, Z);
234
			cgen(r, &nod1);
235
		} else {
236
			regalloc(&nod1, r, Z);
237
			cgen(r, &nod1);
238
			if(l->addable < INDEXED)
239
				reglcgen(&nod2, l, Z);
240
			else
241
				nod2 = *l;
242
		}
243
 
244
		regalloc(&nod, n, nn);
245
		gmove(&nod2, &nod);
246
		gopcode(o, &nod1, Z, &nod);
247
		gmove(&nod, &nod2);
248
		if(nn != Z)
249
			gopcode(OAS, &nod, Z, nn);
250
		regfree(&nod);
251
		regfree(&nod1);
252
		if(l->addable < INDEXED)
253
			regfree(&nod2);
254
		break;
255
 
256
	asbitop:
257
		regalloc(&nod4, n, nn);
258
		if(l->complex >= r->complex) {
259
			bitload(l, &nod, &nod1, &nod2, &nod4);
260
			regalloc(&nod3, r, Z);
261
			cgen(r, &nod3);
262
		} else {
263
			regalloc(&nod3, r, Z);
264
			cgen(r, &nod3);
265
			bitload(l, &nod, &nod1, &nod2, &nod4);
266
		}
267
		gmove(&nod, &nod4);
268
		gopcode(o, &nod3, Z, &nod4);
269
		regfree(&nod3);
270
		gmove(&nod4, &nod);
271
		regfree(&nod4);
272
		bitstore(l, &nod, &nod1, &nod2, nn);
273
		break;
274
 
275
	case OADDR:
276
		if(nn == Z) {
277
			nullwarn(l, Z);
278
			break;
279
		}
280
		lcgen(l, nn);
281
		break;
282
 
283
	case OFUNC:
284
		if(l->complex >= FNX) {
285
			if(l->op != OIND)
286
				diag(n, "bad function call");
287
 
288
			regret(&nod, l->left);
289
			cgen(l->left, &nod);
290
			regsalloc(&nod1, l->left);
291
			gopcode(OAS, &nod, Z, &nod1);
292
			regfree(&nod);
293
 
294
			nod = *n;
295
			nod.left = &nod2;
296
			nod2 = *l;
297
			nod2.left = &nod1;
298
			nod2.complex = 1;
299
			cgen(&nod, nn);
300
 
301
			return;
302
		}
303
		o = reg[REGARG];
304
		gargs(r, &nod, &nod1);
305
		if(l->addable < INDEXED) {
306
			reglcgen(&nod, l, Z);
307
			gopcode(OFUNC, Z, Z, &nod);
308
			regfree(&nod);
309
		} else
310
			gopcode(OFUNC, Z, Z, l);
311
		if(REGARG)
312
			if(o != reg[REGARG])
313
				reg[REGARG]--;
314
		if(nn != Z) {
315
			regret(&nod, n);
316
			gopcode(OAS, &nod, Z, nn);
317
			regfree(&nod);
318
		}
319
		break;
320
 
321
	case OIND:
322
		if(nn == Z) {
323
			nullwarn(l, Z);
324
			break;
325
		}
326
		regialloc(&nod, n, nn);
327
		r = l;
328
		while(r->op == OADD)
329
			r = r->right;
330
		if(sconst(r)) {
331
			v = r->vconst;
332
			r->vconst = 0;
333
			cgen(l, &nod);
334
			nod.xoffset += v;
335
			r->vconst = v;
336
		} else
337
			cgen(l, &nod);
338
		regind(&nod, n);
339
		gopcode(OAS, &nod, Z, nn);
340
		regfree(&nod);
341
		break;
342
 
343
	case OEQ:
344
	case ONE:
345
	case OLE:
346
	case OLT:
347
	case OGE:
348
	case OGT:
349
	case OLO:
350
	case OLS:
351
	case OHI:
352
	case OHS:
353
		if(nn == Z) {
354
			nullwarn(l, r);
355
			break;
356
		}
357
		boolgen(n, 1, nn);
358
		break;
359
 
360
	case OANDAND:
361
	case OOROR:
362
		boolgen(n, 1, nn);
363
		if(nn == Z)
364
			patch(p, pc);
365
		break;
366
 
367
	case ONOT:
368
		if(nn == Z) {
369
			nullwarn(l, Z);
370
			break;
371
		}
372
		boolgen(n, 1, nn);
373
		break;
374
 
375
	case OCOMMA:
376
		cgen(l, Z);
377
		cgen(r, nn);
378
		break;
379
 
380
	case OCAST:
381
		if(nn == Z) {
382
			nullwarn(l, Z);
383
			break;
384
		}
385
		/*
386
		 * convert from types l->n->nn
387
		 */
388
		if(nocast(l->type, n->type)) {
389
			if(nocast(n->type, nn->type)) {
390
				cgen(l, nn);
391
				break;
392
			}
393
		}
394
		regalloc(&nod, l, nn);
395
		cgen(l, &nod);
396
		regalloc(&nod1, n, &nod);
397
		gopcode(OAS, &nod, Z, &nod1);
398
		gopcode(OAS, &nod1, Z, nn);
399
		regfree(&nod1);
400
		regfree(&nod);
401
		break;
402
 
403
	case ODOT:
404
		sugen(l, nodrat, l->type->width);
405
		if(nn != Z) {
406
			warn(n, "non-interruptable temporary");
407
			nod = *nodrat;
408
			if(!r || r->op != OCONST) {
409
				diag(n, "DOT and no offset");
410
				break;
411
			}
412
			nod.xoffset += (long)r->vconst;
413
			nod.type = n->type;
414
			cgen(&nod, nn);
415
		}
416
		break;
417
 
418
	case OCOND:
419
		bcgen(l, 1);
420
		p1 = p;
421
		cgen(r->left, nn);
422
		gbranch(OGOTO);
423
		patch(p1, pc);
424
		p1 = p;
425
		cgen(r->right, nn);
426
		patch(p1, pc);
427
		break;
428
 
429
	case OPOSTINC:
430
	case OPOSTDEC:
431
		v = 1;
432
		if(l->type->etype == TIND)
433
			v = l->type->link->width;
434
		if(o == OPOSTDEC)
435
			v = -v;
436
		if(l->op == OBIT)
437
			goto bitinc;
438
		if(nn == Z)
439
			goto pre;
440
 
441
		if(l->addable < INDEXED)
442
			reglcgen(&nod2, l, Z);
443
		else
444
			nod2 = *l;
445
 
446
		regalloc(&nod, l, nn);
447
		gopcode(OAS, &nod2, Z, &nod);
448
		regalloc(&nod1, l, Z);
449
		if(typefd[l->type->etype]) {
450
			regalloc(&nod3, l, Z);
451
			if(v < 0) {
452
				gopcode(OAS, nodfconst(-v), Z, &nod3);
453
				gopcode(OSUB, &nod3, &nod, &nod1);
454
			} else {
455
				gopcode(OAS, nodfconst(v), Z, &nod3);
456
				gopcode(OADD, &nod3, &nod, &nod1);
457
			}
458
			regfree(&nod3);
459
		} else
460
			gopcode(OADD, nodconst(v), &nod, &nod1);
461
		gopcode(OAS, &nod1, Z, &nod2);
462
 
463
		regfree(&nod);
464
		regfree(&nod1);
465
		if(l->addable < INDEXED)
466
			regfree(&nod2);
467
		break;
468
 
469
	case OPREINC:
470
	case OPREDEC:
471
		v = 1;
472
		if(l->type->etype == TIND)
473
			v = l->type->link->width;
474
		if(o == OPREDEC)
475
			v = -v;
476
		if(l->op == OBIT)
477
			goto bitinc;
478
 
479
	pre:
480
		if(l->addable < INDEXED)
481
			reglcgen(&nod2, l, Z);
482
		else
483
			nod2 = *l;
484
 
485
		regalloc(&nod, l, nn);
486
		gopcode(OAS, &nod2, Z, &nod);
487
		if(typefd[l->type->etype]) {
488
			regalloc(&nod3, l, Z);
489
			if(v < 0) {
490
				gopcode(OAS, nodfconst(-v), Z, &nod3);
491
				gopcode(OSUB, &nod3, Z, &nod);
492
			} else {
493
				gopcode(OAS, nodfconst(v), Z, &nod3);
494
				gopcode(OADD, &nod3, Z, &nod);
495
			}
496
			regfree(&nod3);
497
		} else
498
			gopcode(OADD, nodconst(v), Z, &nod);
499
		gopcode(OAS, &nod, Z, &nod2);
500
		if(nn && l->op == ONAME)	/* in x=++i, emit USED(i) */
501
			gins(ANOP, l, Z);
502
 
503
		regfree(&nod);
504
		if(l->addable < INDEXED)
505
			regfree(&nod2);
506
		break;
507
 
508
	bitinc:
509
		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
510
			bitload(l, &nod, &nod1, &nod2, Z);
511
			gopcode(OAS, &nod, Z, nn);
512
			gopcode(OADD, nodconst(v), Z, &nod);
513
			bitstore(l, &nod, &nod1, &nod2, Z);
514
			break;
515
		}
516
		bitload(l, &nod, &nod1, &nod2, nn);
517
		gopcode(OADD, nodconst(v), Z, &nod);
518
		bitstore(l, &nod, &nod1, &nod2, nn);
519
		break;
520
	}
521
	cursafe = curs;
522
}
523
 
524
void
525
reglcgen(Node *t, Node *n, Node *nn)
526
{
527
	Node *r;
528
	long v;
529
 
530
	regialloc(t, n, nn);
531
	if(n->op == OIND) {
532
		r = n->left;
533
		while(r->op == OADD)
534
			r = r->right;
535
		if(sconst(r)) {
536
			v = r->vconst;
537
			r->vconst = 0;
538
			lcgen(n, t);
539
			t->xoffset += v;
540
			r->vconst = v;
541
			regind(t, n);
542
			return;
543
		}
544
	}
545
	lcgen(n, t);
546
	regind(t, n);
547
}
548
 
549
void
550
lcgen(Node *n, Node *nn)
551
{
552
	Prog *p1;
553
	Node nod;
554
 
555
	if(debug['g']) {
556
		prtree(nn, "lcgen lhs");
557
		prtree(n, "lcgen");
558
	}
559
	if(n == Z || n->type == T)
560
		return;
561
	if(nn == Z) {
562
		nn = &nod;
563
		regalloc(&nod, n, Z);
564
	}
565
	switch(n->op) {
566
	default:
567
		if(n->addable < INDEXED) {
568
			diag(n, "unknown op in lcgen: %O", n->op);
569
			break;
570
		}
571
		nod = *n;
572
		nod.op = OADDR;
573
		nod.left = n;
574
		nod.right = Z;
575
		nod.type = types[TIND];
576
		gopcode(OAS, &nod, Z, nn);
577
		break;
578
 
579
	case OCOMMA:
580
		cgen(n->left, n->left);
581
		lcgen(n->right, nn);
582
		break;
583
 
584
	case OIND:
585
		cgen(n->left, nn);
586
		break;
587
 
588
	case OCOND:
589
		bcgen(n->left, 1);
590
		p1 = p;
591
		lcgen(n->right->left, nn);
592
		gbranch(OGOTO);
593
		patch(p1, pc);
594
		p1 = p;
595
		lcgen(n->right->right, nn);
596
		patch(p1, pc);
597
		break;
598
	}
599
}
600
 
601
void
602
bcgen(Node *n, int true)
603
{
604
 
605
	if(n->type == T)
606
		gbranch(OGOTO);
607
	else
608
		boolgen(n, true, Z);
609
}
610
 
611
void
612
boolgen(Node *n, int true, Node *nn)
613
{
614
	int o;
615
	Prog *p1, *p2;
616
	Node *l, *r, nod, nod1;
617
	long curs;
618
 
619
	if(debug['g']) {
620
		prtree(nn, "boolgen lhs");
621
		prtree(n, "boolgen");
622
	}
623
	curs = cursafe;
624
	l = n->left;
625
	r = n->right;
626
	switch(n->op) {
627
 
628
	default:
629
		regalloc(&nod, n, nn);
630
		cgen(n, &nod);
631
		if(nn == Z || typefd[n->type->etype]) {
632
			o = ONE;
633
			if(true)
634
				o = comrel[relindex(o)];
635
			if(typefd[n->type->etype]) {
636
				nodreg(&nod1, n, NREG+FREGZERO);
637
				gopcode(o, &nod, &nod1, Z);
638
			} else
639
				gopcode(o, &nod, Z, Z);
640
			regfree(&nod);
641
			goto com;
642
		}
643
		if(true)
644
			gopcode(OCOND, &nod, nodconst(0), &nod);
645
		else
646
			gopcode(OCOND, nodconst(1), &nod, &nod);
647
		gopcode(OAS, &nod, Z, nn);
648
		regfree(&nod);
649
		break;
650
 
651
	case OCONST:
652
		o = vconst(n);
653
		if(!true)
654
			o = !o;
655
		gbranch(OGOTO);
656
		if(o) {
657
			p1 = p;
658
			gbranch(OGOTO);
659
			patch(p1, pc);
660
		}
661
		goto com;
662
 
663
	case OCOMMA:
664
		cgen(l, Z);
665
		boolgen(r, true, nn);
666
		break;
667
 
668
	case ONOT:
669
		boolgen(l, !true, nn);
670
		break;
671
 
672
	case OCOND:
673
		bcgen(l, 1);
674
		p1 = p;
675
		bcgen(r->left, true);
676
		p2 = p;
677
		gbranch(OGOTO);
678
		patch(p1, pc);
679
		p1 = p;
680
		bcgen(r->right, !true);
681
		patch(p2, pc);
682
		p2 = p;
683
		gbranch(OGOTO);
684
		patch(p1, pc);
685
		patch(p2, pc);
686
		goto com;
687
 
688
	case OANDAND:
689
		if(!true)
690
			goto caseor;
691
 
692
	caseand:
693
		bcgen(l, true);
694
		p1 = p;
695
		bcgen(r, !true);
696
		p2 = p;
697
		patch(p1, pc);
698
		gbranch(OGOTO);
699
		patch(p2, pc);
700
		goto com;
701
 
702
	case OOROR:
703
		if(!true)
704
			goto caseand;
705
 
706
	caseor:
707
		bcgen(l, !true);
708
		p1 = p;
709
		bcgen(r, !true);
710
		p2 = p;
711
		gbranch(OGOTO);
712
		patch(p1, pc);
713
		patch(p2, pc);
714
		goto com;
715
 
716
	case OEQ:
717
	case ONE:
718
	case OLE:
719
	case OLT:
720
	case OGE:
721
	case OGT:
722
	case OHI:
723
	case OHS:
724
	case OLO:
725
	case OLS:
726
		o = n->op;
727
		if(true)
728
			o = comrel[relindex(o)];
729
		if(l->complex >= FNX && r->complex >= FNX) {
730
			regret(&nod, r);
731
			cgen(r, &nod);
732
			regsalloc(&nod1, r);
733
			gopcode(OAS, &nod, Z, &nod1);
734
			regfree(&nod);
735
			nod = *n;
736
			nod.right = &nod1;
737
			boolgen(&nod, true, nn);
738
			break;
739
		}
740
		if(nn != Z && !typefd[l->type->etype]) {
741
			if(l->complex >= r->complex) {
742
				regalloc(&nod1, l, nn);
743
				cgen(l, &nod1);
744
				regalloc(&nod, r, Z);
745
				cgen(r, &nod);
746
			} else {
747
				regalloc(&nod, r, nn);
748
				cgen(r, &nod);
749
				regalloc(&nod1, l, Z);
750
				cgen(l, &nod1);
751
			}
752
			switch(o) {
753
			case OEQ:
754
				gopcode(OSUB, &nod1, &nod, &nod);
755
				gopcode(OCOND, &nod, nodconst(0), &nod);
756
				break;
757
			case ONE:
758
				gopcode(OSUB, &nod1, &nod, &nod);
759
				gopcode(OCOND, nodconst(1), &nod, &nod);
760
				break;
761
			case OLE:
762
				gopcode(OCOMMA, &nod1, &nod, &nod);
763
				break;
764
			case OGT:
765
				gopcode(OCOMMA, &nod1, &nod, &nod);
766
				gopcode(OXOR, nodconst(1), &nod, &nod);
767
				break;
768
			case OLT:
769
				gopcode(OCOMMA, &nod, &nod1, &nod);
770
				gopcode(OXOR, nodconst(1), &nod, &nod);
771
				break;
772
			case OGE:
773
				gopcode(OCOMMA, &nod, &nod1, &nod);
774
				break;
775
			case OLS:
776
				gopcode(OCOND, &nod1, &nod, &nod);
777
				break;
778
			case OHI:
779
				gopcode(OCOND, &nod1, &nod, &nod);
780
				gopcode(OXOR, nodconst(1), &nod, &nod);
781
				break;
782
			case OLO:
783
				gopcode(OCOND, &nod, &nod1, &nod);
784
				gopcode(OXOR, nodconst(1), &nod, &nod);
785
				break;
786
			case OHS:
787
				gopcode(OCOND, &nod, &nod1, &nod);
788
				break;
789
			}
790
			gopcode(OAS, &nod, Z, nn);
791
			regfree(&nod);
792
			regfree(&nod1);
793
			break;
794
		}
795
		if(sconst(l)) {
796
			switch(o) {
797
			default:
798
				if(l->vconst != 0)
799
					break;
800
 
801
			case OGT:
802
			case OHI:
803
			case OLE:
804
			case OLS:
805
				regalloc(&nod, r, nn);
806
				cgen(r, &nod);
807
				gopcode(o, l, &nod, Z);
808
				regfree(&nod);
809
				goto com;
810
			}
811
		}
812
		if(sconst(r)) {
813
			switch(o) {
814
			default:
815
				if(r->vconst != 0)
816
					break;
817
 
818
			case OGE:
819
			case OHS:
820
			case OLT:
821
			case OLO:
822
				regalloc(&nod, l, nn);
823
				cgen(l, &nod);
824
				gopcode(o, &nod, r, Z);
825
				regfree(&nod);
826
				goto com;
827
			}
828
		}
829
		if(l->complex >= r->complex) {
830
			regalloc(&nod1, l, nn);
831
			cgen(l, &nod1);
832
			regalloc(&nod, r, Z);
833
			cgen(r, &nod);
834
		} else {
835
			regalloc(&nod, r, nn);
836
			cgen(r, &nod);
837
			regalloc(&nod1, l, Z);
838
			cgen(l, &nod1);
839
		}
840
		gopcode(o, &nod1, &nod, Z);
841
		regfree(&nod);
842
		regfree(&nod1);
843
 
844
	com:
845
		if(nn != Z) {
846
			p1 = p;
847
			gopcode(OAS, nodconst(1), Z, nn);
848
			gbranch(OGOTO);
849
			p2 = p;
850
			patch(p1, pc);
851
			gopcode(OAS, nodconst(0), Z, nn);
852
			patch(p2, pc);
853
		}
854
		break;
855
	}
856
	cursafe = curs;
857
}
858
 
859
void
860
sugen(Node *n, Node *nn, long w)
861
{
862
	Prog *p1;
863
	Node nod0, nod1, nod2, nod3, nod4, *l, *r;
864
	Type *t;
865
	long pc1;
866
	int i, m, c;
867
 
868
	if(n == Z || n->type == T)
869
		return;
870
	if(debug['g']) {
871
		prtree(nn, "sugen lhs");
872
		prtree(n, "sugen");
873
	}
874
	if(nn == nodrat)
875
		if(w > nrathole)
876
			nrathole = w;
877
	switch(n->op) {
878
	case OIND:
879
		if(nn == Z) {
880
			nullwarn(n->left, Z);
881
			break;
882
		}
883
 
884
	default:
885
		goto copy;
886
 
887
	case OCONST:
888
		if(n->type && typev[n->type->etype]) {
889
			if(nn == Z) {
890
				nullwarn(n->left, Z);
891
				break;
892
			}
893
 
894
			t = nn->type;
895
			nn->type = types[TLONG];
896
			reglcgen(&nod1, nn, Z);
897
			nn->type = t;
898
 
899
			if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
900
				gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
901
			else
902
				gopcode(OAS, nod32const(n->vconst), Z, &nod1);
903
			nod1.xoffset += SZ_LONG;
904
			if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
905
				gopcode(OAS, nod32const(n->vconst), Z, &nod1);
906
			else
907
				gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
908
 
909
			regfree(&nod1);
910
			break;
911
		}
912
		goto copy;
913
 
914
	case ODOT:
915
		l = n->left;
916
		sugen(l, nodrat, l->type->width);
917
		if(nn != Z) {
918
			warn(n, "non-interruptable temporary");
919
			nod1 = *nodrat;
920
			r = n->right;
921
			if(!r || r->op != OCONST) {
922
				diag(n, "DOT and no offset");
923
				break;
924
			}
925
			nod1.xoffset += (long)r->vconst;
926
			nod1.type = n->type;
927
			sugen(&nod1, nn, w);
928
		}
929
		break;
930
 
931
	case OSTRUCT:
932
		/*
933
		 * rewrite so lhs has no fn call
934
		 */
935
		if(nn != Z && nn->complex >= FNX) {
936
			nod1 = *n;
937
			nod1.type = typ(TIND, n->type);
938
			regret(&nod2, &nod1);
939
			lcgen(nn, &nod2);
940
			regsalloc(&nod0, &nod1);
941
			gopcode(OAS, &nod2, Z, &nod0);
942
			regfree(&nod2);
943
 
944
			nod1 = *n;
945
			nod1.op = OIND;
946
			nod1.left = &nod0;
947
			nod1.right = Z;
948
			nod1.complex = 1;
949
 
950
			sugen(n, &nod1, w);
951
			return;
952
		}
953
 
954
		r = n->left;
955
		for(t = n->type->link; t != T; t = t->down) {
956
			l = r;
957
			if(r->op == OLIST) {
958
				l = r->left;
959
				r = r->right;
960
			}
961
			if(nn == Z) {
962
				cgen(l, nn);
963
				continue;
964
			}
965
			/*
966
			 * hand craft *(&nn + o) = l
967
			 */
968
			nod0 = znode;
969
			nod0.op = OAS;
970
			nod0.type = t;
971
			nod0.left = &nod1;
972
			nod0.right = l;
973
 
974
			nod1 = znode;
975
			nod1.op = OIND;
976
			nod1.type = t;
977
			nod1.left = &nod2;
978
 
979
			nod2 = znode;
980
			nod2.op = OADD;
981
			nod2.type = typ(TIND, t);
982
			nod2.left = &nod3;
983
			nod2.right = &nod4;
984
 
985
			nod3 = znode;
986
			nod3.op = OADDR;
987
			nod3.type = nod2.type;
988
			nod3.left = nn;
989
 
990
			nod4 = znode;
991
			nod4.op = OCONST;
992
			nod4.type = nod2.type;
993
			nod4.vconst = t->offset;
994
 
995
			ccom(&nod0);
996
			acom(&nod0);
997
			xcom(&nod0);
998
			nod0.addable = 0;
999
 
1000
			cgen(&nod0, Z);
1001
		}
1002
		break;
1003
 
1004
	case OAS:
1005
		if(nn == Z) {
1006
			if(n->addable < INDEXED)
1007
				sugen(n->right, n->left, w);
1008
			break;
1009
		}
1010
		sugen(n->right, nodrat, w);
1011
		warn(n, "non-interruptable temporary");
1012
		sugen(nodrat, n->left, w);
1013
		sugen(nodrat, nn, w);
1014
		break;
1015
 
1016
	case OFUNC:
1017
		if(nn == Z) {
1018
			sugen(n, nodrat, w);
1019
			break;
1020
		}
1021
		if(nn->op != OIND) {
1022
			nn = new1(OADDR, nn, Z);
1023
			nn->type = types[TIND];
1024
			nn->addable = 0;
1025
		} else
1026
			nn = nn->left;
1027
		n = new(OFUNC, n->left, new(OLIST, nn, n->right));
1028
		n->type = types[TVOID];
1029
		n->left->type = types[TVOID];
1030
		cgen(n, Z);
1031
		break;
1032
 
1033
	case OCOND:
1034
		bcgen(n->left, 1);
1035
		p1 = p;
1036
		sugen(n->right->left, nn, w);
1037
		gbranch(OGOTO);
1038
		patch(p1, pc);
1039
		p1 = p;
1040
		sugen(n->right->right, nn, w);
1041
		patch(p1, pc);
1042
		break;
1043
 
1044
	case OCOMMA:
1045
		cgen(n->left, Z);
1046
		sugen(n->right, nn, w);
1047
		break;
1048
	}
1049
	return;
1050
 
1051
copy:
1052
	if(nn == Z)
1053
		return;
1054
	if(n->complex >= FNX && nn->complex >= FNX) {
1055
		t = nn->type;
1056
		nn->type = types[TLONG];
1057
		regialloc(&nod1, nn, Z);
1058
		lcgen(nn, &nod1);
1059
		regsalloc(&nod2, nn);
1060
		nn->type = t;
1061
 
1062
		gopcode(OAS, &nod1, Z, &nod2);
1063
		regfree(&nod1);
1064
 
1065
		nod2.type = typ(TIND, t);
1066
 
1067
		nod1 = nod2;
1068
		nod1.op = OIND;
1069
		nod1.left = &nod2;
1070
		nod1.right = Z;
1071
		nod1.complex = 1;
1072
		nod1.type = t;
1073
 
1074
		sugen(n, &nod1, w);
1075
		return;
1076
	}
1077
 
1078
	if(n->complex > nn->complex) {
1079
		t = n->type;
1080
		n->type = types[TLONG];
1081
		reglcgen(&nod1, n, Z);
1082
		n->type = t;
1083
 
1084
		t = nn->type;
1085
		nn->type = types[TLONG];
1086
		reglcgen(&nod2, nn, Z);
1087
		nn->type = t;
1088
	} else {
1089
		t = nn->type;
1090
		nn->type = types[TLONG];
1091
		reglcgen(&nod2, nn, Z);
1092
		nn->type = t;
1093
 
1094
		t = n->type;
1095
		n->type = types[TLONG];
1096
		reglcgen(&nod1, n, Z);
1097
		n->type = t;
1098
	}
1099
 
1100
	w /= SZ_LONG;
1101
	if(w <= 5) {
1102
		layout(&nod1, &nod2, w, 0, Z);
1103
		goto out;
1104
	}
1105
 
1106
	/*
1107
	 * minimize space for unrolling loop
1108
	 * 3,4,5 times. (6 or more is never minimum)
1109
	 * if small structure, try 2 also.
1110
	 */
1111
	c = 0; /* set */
1112
	m = 100;
1113
	i = 3;
1114
	if(w <= 15)
1115
		i = 2;
1116
	for(; i<=5; i++)
1117
		if(i + w%i <= m) {
1118
			c = i;
1119
			m = c + w%c;
1120
		}
1121
 
1122
	regalloc(&nod3, &regnode, Z);
1123
	layout(&nod1, &nod2, w%c, w/c, &nod3);
1124
 
1125
	pc1 = pc;
1126
	layout(&nod1, &nod2, c, 0, Z);
1127
 
1128
	gopcode(OSUB, nodconst(1), Z, &nod3);
1129
	nod1.op = OREGISTER;
1130
	gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod1);
1131
	nod2.op = OREGISTER;
1132
	gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod2);
1133
 
1134
	gopcode(OEQ, &nod3, Z, Z);
1135
	p->as = ABGTZ;
1136
	patch(p, pc1);
1137
 
1138
	regfree(&nod3);
1139
out:
1140
	regfree(&nod1);
1141
	regfree(&nod2);
1142
}
1143
 
1144
void
1145
layout(Node *f, Node *t, int c, int cv, Node *cn)
1146
{
1147
	Node t1, t2;
1148
 
1149
	while(c > 3) {
1150
		layout(f, t, 2, 0, Z);
1151
		c -= 2;
1152
	}
1153
 
1154
	regalloc(&t1, &regnode, Z);
1155
	regalloc(&t2, &regnode, Z);
1156
	t1.type = types[TLONG];
1157
	t2.type = types[TLONG];
1158
	if(c > 0) {
1159
		gopcode(OAS, f, Z, &t1);
1160
		f->xoffset += SZ_LONG;
1161
	}
1162
	if(cn != Z)
1163
		gopcode(OAS, nodconst(cv), Z, cn);
1164
	if(c > 1) {
1165
		gopcode(OAS, f, Z, &t2);
1166
		f->xoffset += SZ_LONG;
1167
	}
1168
	if(c > 0) {
1169
		gopcode(OAS, &t1, Z, t);
1170
		t->xoffset += SZ_LONG;
1171
	}
1172
	if(c > 2) {
1173
		gopcode(OAS, f, Z, &t1);
1174
		f->xoffset += SZ_LONG;
1175
	}
1176
	if(c > 1) {
1177
		gopcode(OAS, &t2, Z, t);
1178
		t->xoffset += SZ_LONG;
1179
	}
1180
	if(c > 2) {
1181
		gopcode(OAS, &t1, Z, t);
1182
		t->xoffset += SZ_LONG;
1183
	}
1184
	regfree(&t1);
1185
	regfree(&t2);
1186
}