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) {
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 OMUL:
161
	case OLMUL:
162
	case OLDIV:
163
	case OLMOD:
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
			if(debug['M'])
174
				print("%L multiply\n", n->lineno);
175
		}
176
		if(l->complex >= r->complex) {
177
			regalloc(&nod, l, nn);
178
			cgen(l, &nod);
179
			regalloc(&nod1, r, Z);
180
			cgen(r, &nod1);
181
			gopcode(o, &nod1, Z, &nod);
182
		} else {
183
			regalloc(&nod, r, nn);
184
			cgen(r, &nod);
185
			regalloc(&nod1, l, Z);
186
			cgen(l, &nod1);
187
			gopcode(o, &nod, &nod1, &nod);
188
		}
189
		gopcode(OAS, &nod, Z, nn);
190
		regfree(&nod);
191
		regfree(&nod1);
192
		break;
193
 
194
	case OASLSHR:
195
	case OASASHL:
196
	case OASASHR:
197
	case OASAND:
198
	case OASADD:
199
	case OASSUB:
200
	case OASXOR:
201
	case OASOR:
202
		if(l->op == OBIT)
203
			goto asbitop;
204
		if(r->op == OCONST)
205
		if(!typefd[n->type->etype]) {
206
			if(l->addable < INDEXED)
207
				reglcgen(&nod2, l, Z);
208
			else
209
				nod2 = *l;
210
			regalloc(&nod, r, nn);
211
			gopcode(OAS, &nod2, Z, &nod);
212
			gopcode(o, r, Z, &nod);
213
			gopcode(OAS, &nod, Z, &nod2);
214
 
215
			regfree(&nod);
216
			if(l->addable < INDEXED)
217
				regfree(&nod2);
218
			break;
219
		}
220
 
221
	case OASLMUL:
222
	case OASLDIV:
223
	case OASLMOD:
224
	case OASMUL:
225
	case OASDIV:
226
	case OASMOD:
227
		if(l->op == OBIT)
228
			goto asbitop;
229
		if(l->complex >= r->complex) {
230
			if(l->addable < INDEXED)
231
				reglcgen(&nod2, l, Z);
232
			else
233
				nod2 = *l;
234
			regalloc(&nod, n, nn);
235
			cgen(r, &nod);
236
		} else {
237
			regalloc(&nod, n, nn);
238
			cgen(r, &nod);
239
			if(l->addable < INDEXED)
240
				reglcgen(&nod2, l, Z);
241
			else
242
				nod2 = *l;
243
		}
244
		regalloc(&nod1, n, Z);
245
		gopcode(OAS, &nod2, Z, &nod1);
246
		gopcode(o, &nod, &nod1, &nod);
247
		gopcode(OAS, &nod, Z, &nod2);
248
		regfree(&nod);
249
		regfree(&nod1);
250
		if(l->addable < INDEXED)
251
			regfree(&nod2);
252
		break;
253
 
254
	asbitop:
255
		regalloc(&nod4, n, nn);
256
		regalloc(&nod3, r, Z);
257
		if(l->complex >= r->complex) {
258
			bitload(l, &nod, &nod1, &nod2, &nod4);
259
			cgen(r, &nod3);
260
		} else {
261
			cgen(r, &nod3);
262
			bitload(l, &nod, &nod1, &nod2, &nod4);
263
		}
264
		gmove(&nod, &nod4);
265
		gopcode(n->op, &nod3, Z, &nod4);
266
		regfree(&nod3);
267
		gmove(&nod4, &nod);
268
		regfree(&nod4);
269
		bitstore(l, &nod, &nod1, &nod2, nn);
270
		break;
271
 
272
	case OADDR:
273
		if(nn == Z) {
274
			nullwarn(l, Z);
275
			break;
276
		}
277
		lcgen(l, nn);
278
		break;
279
 
280
	case OFUNC:
281
		if(l->complex >= FNX) {
282
			if(l->op != OIND)
283
				diag(n, "bad function call");
284
 
285
			regret(&nod, l->left);
286
			cgen(l->left, &nod);
287
			regsalloc(&nod1, l->left);
288
			gopcode(OAS, &nod, Z, &nod1);
289
			regfree(&nod);
290
 
291
			nod = *n;
292
			nod.left = &nod2;
293
			nod2 = *l;
294
			nod2.left = &nod1;
295
			nod2.complex = 1;
296
			cgen(&nod, nn);
297
 
298
			return;
299
		}
300
		o = reg[REGARG];
301
		gargs(r, &nod, &nod1);
302
		if(l->addable < INDEXED) {
303
			reglcgen(&nod, l, Z);
304
			gopcode(OFUNC, Z, Z, &nod);
305
			regfree(&nod);
306
		} else
307
			gopcode(OFUNC, Z, Z, l);
308
		if(REGARG)
309
			if(o != reg[REGARG])
310
				reg[REGARG]--;
311
		if(nn != Z) {
312
			regret(&nod, n);
313
			gopcode(OAS, &nod, Z, nn);
314
			regfree(&nod);
315
		}
316
		break;
317
 
318
	case OIND:
319
		if(nn == Z) {
320
			cgen(l, nn);
321
			break;
322
		}
323
		regialloc(&nod, n, nn);
324
		r = l;
325
		while(r->op == OADD)
326
			r = r->right;
327
		if(sconst(r)) {
328
			v = r->vconst;
329
			r->vconst = 0;
330
			cgen(l, &nod);
331
			nod.xoffset += v;
332
			r->vconst = v;
333
		} else
334
			cgen(l, &nod);
335
		regind(&nod, n);
336
		gopcode(OAS, &nod, Z, nn);
337
		regfree(&nod);
338
		break;
339
 
340
	case OEQ:
341
	case ONE:
342
	case OLE:
343
	case OLT:
344
	case OGE:
345
	case OGT:
346
	case OLO:
347
	case OLS:
348
	case OHI:
349
	case OHS:
350
		if(nn == Z) {
351
			nullwarn(l, r);
352
			break;
353
		}
354
		boolgen(n, 1, nn);
355
		break;
356
 
357
	case OANDAND:
358
	case OOROR:
359
		boolgen(n, 1, nn);
360
		if(nn == Z)
361
			patch(p, pc);
362
		break;
363
 
364
	case ONOT:
365
		if(nn == Z) {
366
			nullwarn(l, Z);
367
			break;
368
		}
369
		boolgen(n, 1, nn);
370
		break;
371
 
372
	case OCOMMA:
373
		cgen(l, Z);
374
		cgen(r, nn);
375
		break;
376
 
377
	case OCAST:
378
		if(nn == Z) {
379
			nullwarn(l, Z);
380
			break;
381
		}
382
		/*
383
		 * convert from types l->n->nn
384
		 */
385
		if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
386
			/* both null, gen l->nn */
387
			cgen(l, nn);
388
			break;
389
		}
390
		regalloc(&nod, l, nn);
391
		cgen(l, &nod);
392
		regalloc(&nod1, n, &nod);
393
		gopcode(OAS, &nod, Z, &nod1);
394
		gopcode(OAS, &nod1, Z, nn);
395
		regfree(&nod1);
396
		regfree(&nod);
397
		break;
398
 
399
	case ODOT:
400
		sugen(l, nodrat, l->type->width);
401
		if(nn != Z) {
402
			warn(n, "non-interruptable temporary");
403
			nod = *nodrat;
404
			if(!r || r->op != OCONST) {
405
				diag(n, "DOT and no offset");
406
				break;
407
			}
408
			nod.xoffset += (long)r->vconst;
409
			nod.type = n->type;
410
			cgen(&nod, nn);
411
		}
412
		break;
413
 
414
	case OCOND:
415
		bcgen(l, 1);
416
		p1 = p;
417
		cgen(r->left, nn);
418
		gbranch(OGOTO);
419
		patch(p1, pc);
420
		p1 = p;
421
		cgen(r->right, nn);
422
		patch(p1, pc);
423
		break;
424
 
425
	case OPOSTINC:
426
	case OPOSTDEC:
427
		v = 1;
428
		if(l->type->etype == TIND)
429
			v = l->type->link->width;
430
		if(o == OPOSTDEC)
431
			v = -v;
432
		if(l->op == OBIT)
433
			goto bitinc;
434
		if(nn == Z)
435
			goto pre;
436
 
437
		if(l->addable < INDEXED)
438
			reglcgen(&nod2, l, Z);
439
		else
440
			nod2 = *l;
441
 
442
		regalloc(&nod, l, nn);
443
		gopcode(OAS, &nod2, Z, &nod);
444
		regalloc(&nod1, l, Z);
445
		if(typefd[l->type->etype]) {
446
			regalloc(&nod3, l, Z);
447
			if(v < 0) {
448
				gopcode(OAS, nodfconst(-v), Z, &nod3);
449
				gopcode(OSUB, &nod3, &nod, &nod1);
450
			} else {
451
				gopcode(OAS, nodfconst(v), Z, &nod3);
452
				gopcode(OADD, &nod3, &nod, &nod1);
453
			}
454
			regfree(&nod3);
455
		} else
456
			gopcode(OADD, nodconst(v), &nod, &nod1);
457
		gopcode(OAS, &nod1, Z, &nod2);
458
 
459
		regfree(&nod);
460
		regfree(&nod1);
461
		if(l->addable < INDEXED)
462
			regfree(&nod2);
463
		break;
464
 
465
	case OPREINC:
466
	case OPREDEC:
467
		v = 1;
468
		if(l->type->etype == TIND)
469
			v = l->type->link->width;
470
		if(o == OPREDEC)
471
			v = -v;
472
		if(l->op == OBIT)
473
			goto bitinc;
474
 
475
	pre:
476
		if(l->addable < INDEXED)
477
			reglcgen(&nod2, l, Z);
478
		else
479
			nod2 = *l;
480
 
481
		regalloc(&nod, l, nn);
482
		gopcode(OAS, &nod2, Z, &nod);
483
		if(typefd[l->type->etype]) {
484
			regalloc(&nod3, l, Z);
485
			if(v < 0) {
486
				gopcode(OAS, nodfconst(-v), Z, &nod3);
487
				gopcode(OSUB, &nod3, Z, &nod);
488
			} else {
489
				gopcode(OAS, nodfconst(v), Z, &nod3);
490
				gopcode(OADD, &nod3, Z, &nod);
491
			}
492
			regfree(&nod3);
493
		} else
494
			gopcode(OADD, nodconst(v), Z, &nod);
495
		gopcode(OAS, &nod, Z, &nod2);
496
		if(nn && l->op == ONAME)	/* in x=++i, emit USED(i) */
497
			gins(ANOP, l, Z);
498
 
499
		regfree(&nod);
500
		if(l->addable < INDEXED)
501
			regfree(&nod2);
502
		break;
503
 
504
	bitinc:
505
		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
506
			bitload(l, &nod, &nod1, &nod2, Z);
507
			gopcode(OAS, &nod, Z, nn);
508
			gopcode(OADD, nodconst(v), Z, &nod);
509
			bitstore(l, &nod, &nod1, &nod2, Z);
510
			break;
511
		}
512
		bitload(l, &nod, &nod1, &nod2, nn);
513
		gopcode(OADD, nodconst(v), Z, &nod);
514
		bitstore(l, &nod, &nod1, &nod2, nn);
515
		break;
516
	}
517
	cursafe = curs;
518
}
519
 
520
void
521
reglcgen(Node *t, Node *n, Node *nn)
522
{
523
	Node *r;
524
	long v;
525
 
526
	regialloc(t, n, nn);
527
	if(n->op == OIND) {
528
		r = n->left;
529
		while(r->op == OADD)
530
			r = r->right;
531
		if(sconst(r)) {
532
			v = r->vconst;
533
			r->vconst = 0;
534
			lcgen(n, t);
535
			t->xoffset += v;
536
			r->vconst = v;
537
			regind(t, n);
538
			return;
539
		}
540
	}
541
	lcgen(n, t);
542
	regind(t, n);
543
}
544
 
545
void
546
lcgen(Node *n, Node *nn)
547
{
548
	Prog *p1;
549
	Node nod;
550
 
551
	if(debug['g']) {
552
		prtree(nn, "lcgen lhs");
553
		prtree(n, "lcgen");
554
	}
555
	if(n == Z || n->type == T)
556
		return;
557
	if(nn == Z) {
558
		nn = &nod;
559
		regalloc(&nod, n, Z);
560
	}
561
	switch(n->op) {
562
	default:
563
		if(n->addable < INDEXED) {
564
			diag(n, "unknown op in lcgen: %O", n->op);
565
			break;
566
		}
567
		nod = *n;
568
		nod.op = OADDR;
569
		nod.left = n;
570
		nod.right = Z;
571
		nod.type = types[TIND];
572
		gopcode(OAS, &nod, Z, nn);
573
		break;
574
 
575
	case OCOMMA:
576
		cgen(n->left, n->left);
577
		lcgen(n->right, nn);
578
		break;
579
 
580
	case OIND:
581
		cgen(n->left, nn);
582
		break;
583
 
584
	case OCOND:
585
		bcgen(n->left, 1);
586
		p1 = p;
587
		lcgen(n->right->left, nn);
588
		gbranch(OGOTO);
589
		patch(p1, pc);
590
		p1 = p;
591
		lcgen(n->right->right, nn);
592
		patch(p1, pc);
593
		break;
594
	}
595
}
596
 
597
void
598
bcgen(Node *n, int true)
599
{
600
 
601
	if(n->type == T)
602
		gbranch(OGOTO);
603
	else
604
		boolgen(n, true, Z);
605
}
606
 
607
void
608
boolgen(Node *n, int true, Node *nn)
609
{
610
	int o;
611
	Prog *p1, *p2;
612
	Node *l, *r, nod, nod1;
613
	long curs;
614
 
615
	if(debug['g']) {
616
		prtree(nn, "boolgen lhs");
617
		prtree(n, "boolgen");
618
	}
619
	curs = cursafe;
620
	l = n->left;
621
	r = n->right;
622
	switch(n->op) {
623
 
624
	default:
625
		if(n->op == OCONST) {
626
			o = vconst(n);
627
			if(!true)
628
				o = !o;
629
			gbranch(OGOTO);
630
			if(o) {
631
				p1 = p;
632
				gbranch(OGOTO);
633
				patch(p1, pc);
634
			}
635
			goto com;
636
		}
637
		regalloc(&nod, n, nn);
638
		cgen(n, &nod);
639
		o = ONE;
640
		if(true)
641
			o = comrel[relindex(o)];
642
		if(typefd[n->type->etype]) {
643
			nodreg(&nod1, n, NREG+FREGZERO);
644
			gopcode(o, &nod, Z, &nod1);
645
		} else
646
			gopcode(o, &nod, Z, nodconst(0));
647
		regfree(&nod);
648
		goto com;
649
 
650
	case OCOMMA:
651
		cgen(l, Z);
652
		boolgen(r, true, nn);
653
		break;
654
 
655
	case ONOT:
656
		boolgen(l, !true, nn);
657
		break;
658
 
659
	case OCOND:
660
		bcgen(l, 1);
661
		p1 = p;
662
		bcgen(r->left, true);
663
		p2 = p;
664
		gbranch(OGOTO);
665
		patch(p1, pc);
666
		p1 = p;
667
		bcgen(r->right, !true);
668
		patch(p2, pc);
669
		p2 = p;
670
		gbranch(OGOTO);
671
		patch(p1, pc);
672
		patch(p2, pc);
673
		goto com;
674
 
675
	case OANDAND:
676
		if(!true)
677
			goto caseor;
678
 
679
	caseand:
680
		bcgen(l, true);
681
		p1 = p;
682
		bcgen(r, !true);
683
		p2 = p;
684
		patch(p1, pc);
685
		gbranch(OGOTO);
686
		patch(p2, pc);
687
		goto com;
688
 
689
	case OOROR:
690
		if(!true)
691
			goto caseand;
692
 
693
	caseor:
694
		bcgen(l, !true);
695
		p1 = p;
696
		bcgen(r, !true);
697
		p2 = p;
698
		gbranch(OGOTO);
699
		patch(p1, pc);
700
		patch(p2, pc);
701
		goto com;
702
 
703
	case OEQ:
704
	case ONE:
705
	case OLE:
706
	case OLT:
707
	case OGE:
708
	case OGT:
709
	case OHI:
710
	case OHS:
711
	case OLO:
712
	case OLS:
713
		o = n->op;
714
		if(true)
715
			o = comrel[relindex(o)];
716
		if(l->complex >= FNX && r->complex >= FNX) {
717
			regret(&nod, r);
718
			cgen(r, &nod);
719
			regsalloc(&nod1, r);
720
			gopcode(OAS, &nod, Z, &nod1);
721
			regfree(&nod);
722
			nod = *n;
723
			nod.right = &nod1;
724
			boolgen(&nod, true, nn);
725
			break;
726
		}
727
		if(sconst(r)) {
728
			regalloc(&nod, l, nn);
729
			cgen(l, &nod);
730
			gopcode(o, &nod, Z, r);
731
			regfree(&nod);
732
			goto com;
733
		}
734
		if(l->complex >= r->complex) {
735
			regalloc(&nod1, l, nn);
736
			cgen(l, &nod1);
737
			regalloc(&nod, r, Z);
738
			cgen(r, &nod);
739
		} else {
740
			regalloc(&nod, r, nn);
741
			cgen(r, &nod);
742
			regalloc(&nod1, l, Z);
743
			cgen(l, &nod1);
744
		}
745
		gopcode(o, &nod1, Z, &nod);
746
		regfree(&nod);
747
		regfree(&nod1);
748
 
749
	com:
750
		if(nn != Z) {
751
			p1 = p;
752
			gopcode(OAS, nodconst(1L), Z, nn);
753
			gbranch(OGOTO);
754
			p2 = p;
755
			patch(p1, pc);
756
			gopcode(OAS, nodconst(0L), Z, nn);
757
			patch(p2, pc);
758
		}
759
		break;
760
	}
761
	cursafe = curs;
762
}
763
 
764
void
765
sugen(Node *n, Node *nn, long w)
766
{
767
	Prog *p1;
768
	Node nod0, nod1, nod2, nod3, nod4, *l, *r;
769
	Type *t;
770
	long pc1;
771
	int i, m, c;
772
 
773
	if(n == Z || n->type == T)
774
		return;
775
	if(debug['g']) {
776
		prtree(nn, "sugen lhs");
777
		prtree(n, "sugen");
778
	}
779
	if(nn == nodrat)
780
		if(w > nrathole)
781
			nrathole = w;
782
	switch(n->op) {
783
	case OIND:
784
		if(nn == Z) {
785
			nullwarn(n->left, Z);
786
			break;
787
		}
788
 
789
	default:
790
		goto copy;
791
 
792
	case OCONST:
793
		if(n->type && typev[n->type->etype]) {
794
			if(nn == Z) {
795
				nullwarn(n->left, Z);
796
				break;
797
			}
798
 
799
			t = nn->type;
800
			nn->type = types[TLONG];
801
			reglcgen(&nod1, nn, Z);
802
			nn->type = t;
803
 
804
			if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
805
				gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
806
			else
807
				gopcode(OAS, nod32const(n->vconst), Z, &nod1);
808
			nod1.xoffset += SZ_LONG;
809
			if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
810
				gopcode(OAS, nod32const(n->vconst), Z, &nod1);
811
			else
812
				gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
813
 
814
			regfree(&nod1);
815
			break;
816
		}
817
		goto copy;
818
 
819
	case ODOT:
820
		l = n->left;
821
		sugen(l, nodrat, l->type->width);
822
		if(nn != Z) {
823
			warn(n, "non-interruptable temporary");
824
			nod1 = *nodrat;
825
			r = n->right;
826
			if(!r || r->op != OCONST) {
827
				diag(n, "DOT and no offset");
828
				break;
829
			}
830
			nod1.xoffset += (long)r->vconst;
831
			nod1.type = n->type;
832
			sugen(&nod1, nn, w);
833
		}
834
		break;
835
 
836
	case OSTRUCT:
837
		/*
838
		 * rewrite so lhs has no fn call
839
		 */
840
		if(nn != Z && nn->complex >= FNX) {
841
			nod1 = *n;
842
			nod1.type = typ(TIND, n->type);
843
			regret(&nod2, &nod1);
844
			lcgen(nn, &nod2);
845
			regsalloc(&nod0, &nod1);
846
			gopcode(OAS, &nod2, Z, &nod0);
847
			regfree(&nod2);
848
 
849
			nod1 = *n;
850
			nod1.op = OIND;
851
			nod1.left = &nod0;
852
			nod1.right = Z;
853
			nod1.complex = 1;
854
 
855
			sugen(n, &nod1, w);
856
			return;
857
		}
858
 
859
		r = n->left;
860
		for(t = n->type->link; t != T; t = t->down) {
861
			l = r;
862
			if(r->op == OLIST) {
863
				l = r->left;
864
				r = r->right;
865
			}
866
			if(nn == Z) {
867
				cgen(l, nn);
868
				continue;
869
			}
870
			/*
871
			 * hand craft *(&nn + o) = l
872
			 */
873
			nod0 = znode;
874
			nod0.op = OAS;
875
			nod0.type = t;
876
			nod0.left = &nod1;
877
			nod0.right = l;
878
 
879
			nod1 = znode;
880
			nod1.op = OIND;
881
			nod1.type = t;
882
			nod1.left = &nod2;
883
 
884
			nod2 = znode;
885
			nod2.op = OADD;
886
			nod2.type = typ(TIND, t);
887
			nod2.left = &nod3;
888
			nod2.right = &nod4;
889
 
890
			nod3 = znode;
891
			nod3.op = OADDR;
892
			nod3.type = nod2.type;
893
			nod3.left = nn;
894
 
895
			nod4 = znode;
896
			nod4.op = OCONST;
897
			nod4.type = nod2.type;
898
			nod4.vconst = t->offset;
899
 
900
			ccom(&nod0);
901
			acom(&nod0);
902
			xcom(&nod0);
903
			nod0.addable = 0;
904
 
905
			cgen(&nod0, Z);
906
		}
907
		break;
908
 
909
	case OAS:
910
		if(nn == Z) {
911
			if(n->addable < INDEXED)
912
				sugen(n->right, n->left, w);
913
			break;
914
		}
915
		/* BOTCH -- functions can clobber rathole */
916
		sugen(n->right, nodrat, w);
917
		warn(n, "non-interruptable temporary");
918
		sugen(nodrat, n->left, w);
919
		sugen(nodrat, nn, w);
920
		break;
921
 
922
	case OFUNC:
923
		if(nn == Z) {
924
			sugen(n, nodrat, w);
925
			break;
926
		}
927
		if(nn->op != OIND) {
928
			nn = new1(OADDR, nn, Z);
929
			nn->type = types[TIND];
930
			nn->addable = 0;
931
		} else
932
			nn = nn->left;
933
		n = new(OFUNC, n->left, new(OLIST, nn, n->right));
934
		n->type = types[TVOID];
935
		n->left->type = types[TVOID];
936
		cgen(n, Z);
937
		break;
938
 
939
	case OCOND:
940
		bcgen(n->left, 1);
941
		p1 = p;
942
		sugen(n->right->left, nn, w);
943
		gbranch(OGOTO);
944
		patch(p1, pc);
945
		p1 = p;
946
		sugen(n->right->right, nn, w);
947
		patch(p1, pc);
948
		break;
949
 
950
	case OCOMMA:
951
		cgen(n->left, Z);
952
		sugen(n->right, nn, w);
953
		break;
954
	}
955
	return;
956
 
957
copy:
958
	if(nn == Z)
959
		return;
960
	if(n->complex >= FNX && nn->complex >= FNX) {
961
		t = nn->type;
962
		nn->type = types[TLONG];
963
		regialloc(&nod1, nn, Z);
964
		lcgen(nn, &nod1);
965
		regsalloc(&nod2, nn);
966
		nn->type = t;
967
 
968
		gopcode(OAS, &nod1, Z, &nod2);
969
		regfree(&nod1);
970
 
971
		nod2.type = typ(TIND, t);
972
 
973
		nod1 = nod2;
974
		nod1.op = OIND;
975
		nod1.left = &nod2;
976
		nod1.right = Z;
977
		nod1.complex = 1;
978
		nod1.type = t;
979
 
980
		sugen(n, &nod1, w);
981
		return;
982
	}
983
 
984
	if(n->complex > nn->complex) {
985
		t = n->type;
986
		n->type = types[TLONG];
987
		reglcgen(&nod1, n, Z);
988
		n->type = t;
989
 
990
		t = nn->type;
991
		nn->type = types[TLONG];
992
		reglcgen(&nod2, nn, Z);
993
		nn->type = t;
994
	} else {
995
		t = nn->type;
996
		nn->type = types[TLONG];
997
		reglcgen(&nod2, nn, Z);
998
		nn->type = t;
999
 
1000
		t = n->type;
1001
		n->type = types[TLONG];
1002
		reglcgen(&nod1, n, Z);
1003
		n->type = t;
1004
	}
1005
 
1006
	w /= SZ_LONG;
1007
	if(w <= 5) {
1008
		layout(&nod1, &nod2, w, 0, Z);
1009
		goto out;
1010
	}
1011
 
1012
	/*
1013
	 * minimize space for unrolling loop
1014
	 * 3,4,5 times. (6 or more is never minimum)
1015
	 * if small structure, try 2 also.
1016
	 */
1017
	c = 0; /* set */
1018
	m = 100;
1019
	i = 3;
1020
	if(w <= 15)
1021
		i = 2;
1022
	for(; i<=5; i++)
1023
		if(i + w%i <= m) {
1024
			c = i;
1025
			m = c + w%c;
1026
		}
1027
 
1028
	regalloc(&nod3, &regnode, Z);
1029
	layout(&nod1, &nod2, w%c, w/c, &nod3);
1030
 
1031
	pc1 = pc;
1032
	layout(&nod1, &nod2, c, 0, Z);
1033
 
1034
	gopcode(OSUB, nodconst(1L), Z, &nod3);
1035
	nod1.op = OREGISTER;
1036
	gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod1);
1037
	nod2.op = OREGISTER;
1038
	gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod2);
1039
 
1040
	gopcode(OGT, &nod3, Z, nodconst(0));
1041
	patch(p, pc1);
1042
 
1043
	regfree(&nod3);
1044
out:
1045
	regfree(&nod1);
1046
	regfree(&nod2);
1047
}
1048
 
1049
void
1050
layout(Node *f, Node *t, int c, int cv, Node *cn)
1051
{
1052
	Node t1, t2;
1053
 
1054
	while(c > 3) {
1055
		layout(f, t, 2, 0, Z);
1056
		c -= 2;
1057
	}
1058
 
1059
	regalloc(&t1, &regnode, Z);
1060
	regalloc(&t2, &regnode, Z);
1061
	if(c > 0) {
1062
		gopcode(OAS, f, Z, &t1);
1063
		f->xoffset += SZ_LONG;
1064
	}
1065
	if(cn != Z)
1066
		gopcode(OAS, nodconst(cv), Z, cn);
1067
	if(c > 1) {
1068
		gopcode(OAS, f, Z, &t2);
1069
		f->xoffset += SZ_LONG;
1070
	}
1071
	if(c > 0) {
1072
		gopcode(OAS, &t1, Z, t);
1073
		t->xoffset += SZ_LONG;
1074
	}
1075
	if(c > 2) {
1076
		gopcode(OAS, f, Z, &t1);
1077
		f->xoffset += SZ_LONG;
1078
	}
1079
	if(c > 1) {
1080
		gopcode(OAS, &t2, Z, t);
1081
		t->xoffset += SZ_LONG;
1082
	}
1083
	if(c > 2) {
1084
		gopcode(OAS, &t1, Z, t);
1085
		t->xoffset += SZ_LONG;
1086
	}
1087
	regfree(&t1);
1088
	regfree(&t2);
1089
}