changelog shortlog tags branches changeset files revisions annotate raw help

Mercurial > hg > plan9front / sys/src/cmd/qc/cgen.c

changeset 7179: b3b84087ac92
parent: 3dd7e5a4f49a
child: e91d6e59da67
author: cinap_lenrek@felloff.net
date: Wed, 01 May 2019 08:55:24 +0200
permissions: -rw-r--r--
description: [5678vq]c: fix .safe node type for *FUNC() = *FUNC() sugen
1 #include "gc.h"
2 
3 static void cmpv(Node*, int, Node*);
4 static void testv(Node*, int);
5 static void cgen64(Node*, Node*);
6 static int isvconstable(int, vlong);
7 static void genasop(int, Node*, Node*, Node*);
8 
9 void
10 cgen(Node *n, Node *nn)
11 {
12  Node *l, *r;
13  Prog *p1;
14  Node nod, nod1, nod2, nod3, nod4;
15  int o;
16  long v, curs;
17 
18  if(debug['g']) {
19  prtree(nn, "cgen lhs");
20  prtree(n, "cgen");
21  }
22  if(n == Z || n->type == T)
23  return;
24  if(typesu[n->type->etype]) {
25  sugen(n, nn, n->type->width);
26  return;
27  }
28  if(typev[n->type->etype]) {
29  switch(n->op) {
30  case OCONST:
31  case OFUNC:
32  cgen64(n, nn);
33  return;
34  }
35  }
36  l = n->left;
37  r = n->right;
38  o = n->op;
39  if(n->addable >= INDEXED) {
40  if(nn == Z) {
41  switch(o) {
42  default:
43  nullwarn(Z, Z);
44  break;
45  case OINDEX:
46  nullwarn(l, r);
47  break;
48  }
49  return;
50  }
51  gmove(n, nn);
52  return;
53  }
54  curs = cursafe;
55 
56  if(n->complex >= FNX)
57  if(l->complex >= FNX)
58  if(r != Z && r->complex >= FNX)
59  switch(o) {
60  default:
61  if(!typev[r->type->etype]) {
62  regret(&nod, r);
63  cgen(r, &nod);
64  regsalloc(&nod1, r);
65  gmove(&nod, &nod1);
66  regfree(&nod);
67  } else {
68  regsalloc(&nod1, r);
69  cgen(r, &nod1);
70  }
71 
72  nod = *n;
73  nod.right = &nod1;
74  cgen(&nod, nn);
75  return;
76 
77  case OFUNC:
78  case OCOMMA:
79  case OANDAND:
80  case OOROR:
81  case OCOND:
82  case ODOT:
83  break;
84  }
85 
86  switch(o) {
87  default:
88  diag(n, "unknown op in cgen: %O", o);
89  break;
90 
91  case ONEG:
92  case OCOM:
93  if(nn == Z) {
94  nullwarn(l, Z);
95  break;
96  }
97  regalloc(&nod, l, nn);
98  cgen(l, &nod);
99  gopcode(o, &nod, Z, &nod);
100  gmove(&nod, nn);
101  regfree(&nod);
102  break;
103 
104  case OAS:
105  if(l->op == OBIT)
106  goto bitas;
107  if(l->addable >= INDEXED) {
108  if(nn != Z || r->addable < INDEXED) {
109  regalloc(&nod, r, nn);
110  cgen(r, &nod);
111  gmove(&nod, l);
112  regfree(&nod);
113  } else
114  gmove(r, l);
115  break;
116  }
117  if(l->complex >= r->complex) {
118  reglcgen(&nod1, l, Z);
119  if(r->addable >= INDEXED) {
120  gmove(r, &nod1);
121  if(nn != Z)
122  gmove(r, nn);
123  regfree(&nod1);
124  break;
125  }
126  regalloc(&nod, r, nn);
127  cgen(r, &nod);
128  } else {
129  regalloc(&nod, r, nn);
130  cgen(r, &nod);
131  reglcgen(&nod1, l, Z);
132  }
133  gmove(&nod, &nod1);
134  regfree(&nod);
135  regfree(&nod1);
136  break;
137 
138  bitas:
139  n = l->left;
140  regalloc(&nod, r, nn);
141  if(l->complex >= r->complex) {
142  reglcgen(&nod1, n, Z);
143  cgen(r, &nod);
144  } else {
145  cgen(r, &nod);
146  reglcgen(&nod1, n, Z);
147  }
148  regalloc(&nod2, n, Z);
149  gopcode(OAS, &nod1, Z, &nod2);
150  bitstore(l, &nod, &nod1, &nod2, nn);
151  break;
152 
153  case OBIT:
154  if(nn == Z) {
155  nullwarn(l, Z);
156  break;
157  }
158  bitload(n, &nod, Z, Z, nn);
159  gopcode(OAS, &nod, Z, nn);
160  regfree(&nod);
161  break;
162 
163  case OXOR:
164  if(nn != Z)
165  if(r->op == OCONST && r->vconst == -1){
166  regalloc(&nod, l, nn);
167  cgen(l, &nod);
168  gopcode(OCOM, &nod, Z, &nod);
169  gmove(&nod, nn);
170  regfree(&nod);
171  break;
172  }
173 
174  case OADD:
175  case OSUB:
176  case OAND:
177  case OOR:
178  case OLSHR:
179  case OASHL:
180  case OASHR:
181  /*
182  * immediate operands
183  */
184  if(nn != Z && r->op == OCONST && !typefd[n->type->etype] &&
185  (!typev[n->type->etype] || isvconstable(o, r->vconst))) {
186  regalloc(&nod, l, nn);
187  cgen(l, &nod);
188  if(o == OAND || r->vconst != 0)
189  gopcode(o, r, Z, &nod);
190  gmove(&nod, nn);
191  regfree(&nod);
192  break;
193  }
194 
195  case OMUL:
196  case OLMUL:
197  case OLDIV:
198  case OLMOD:
199  case ODIV:
200  case OMOD:
201  if(nn == Z) {
202  nullwarn(l, r);
203  break;
204  }
205  if((o == OMUL || o == OLMUL) && !typev[n->type->etype]) {
206  if(mulcon(n, nn))
207  break;
208  if(debug['M'])
209  print("%L multiply\n", n->lineno);
210  }
211  if(l->complex >= r->complex) {
212  regalloc(&nod, l, nn);
213  cgen(l, &nod);
214  if(o != OMUL || typev[n->type->etype] || !sconst(r)) {
215  regalloc(&nod1, r, Z);
216  cgen(r, &nod1);
217  gopcode(o, &nod1, Z, &nod);
218  regfree(&nod1);
219  } else
220  gopcode(o, r, Z, &nod);
221  } else {
222  regalloc(&nod1, r, nn);
223  cgen(r, &nod1);
224  regalloc(&nod, l, Z);
225  cgen(l, &nod);
226  gopcode(o, &nod1, Z, &nod);
227  regfree(&nod1);
228  }
229  gopcode(OAS, &nod, Z, nn);
230  regfree(&nod);
231  break;
232 
233  case OASLSHR:
234  case OASASHL:
235  case OASASHR:
236  case OASAND:
237  case OASADD:
238  case OASSUB:
239  case OASXOR:
240  case OASOR:
241  if(l->op == OBIT)
242  goto asbitop;
243  if(r->op == OCONST && !typefd[r->type->etype] && !typefd[n->type->etype] &&
244  (!typev[n->type->etype] || isvconstable(o, r->vconst))) {
245  if(l->addable < INDEXED)
246  reglcgen(&nod2, l, Z);
247  else
248  nod2 = *l;
249  regalloc(&nod, l, nn);
250  gopcode(OAS, &nod2, Z, &nod);
251  gopcode(o, r, Z, &nod);
252  gopcode(OAS, &nod, Z, &nod2);
253 
254  regfree(&nod);
255  if(l->addable < INDEXED)
256  regfree(&nod2);
257  break;
258  }
259  genasop(o, l, r, nn);
260  break;
261 
262  case OASLMUL:
263  case OASLDIV:
264  case OASLMOD:
265  case OASMUL:
266  case OASDIV:
267  case OASMOD:
268  if(l->op == OBIT)
269  goto asbitop;
270  genasop(o, l, r, nn);
271  break;
272 
273  asbitop:
274  regalloc(&nod4, n, nn);
275  regalloc(&nod3, r, Z);
276  if(l->complex >= r->complex) {
277  bitload(l, &nod, &nod1, &nod2, &nod4);
278  cgen(r, &nod3);
279  } else {
280  cgen(r, &nod3);
281  bitload(l, &nod, &nod1, &nod2, &nod4);
282  }
283  gmove(&nod, &nod4);
284  gopcode(n->op, &nod3, Z, &nod4);
285  regfree(&nod3);
286  gmove(&nod4, &nod);
287  regfree(&nod4);
288  bitstore(l, &nod, &nod1, &nod2, nn);
289  break;
290 
291  case OADDR:
292  if(nn == Z) {
293  nullwarn(l, Z);
294  break;
295  }
296  lcgen(l, nn);
297  break;
298 
299  case OFUNC:
300  if(l->complex >= FNX) {
301  if(l->op != OIND)
302  diag(n, "bad function call");
303 
304  regret(&nod, l->left);
305  cgen(l->left, &nod);
306  regsalloc(&nod1, l->left);
307  gopcode(OAS, &nod, Z, &nod1);
308  regfree(&nod);
309 
310  nod = *n;
311  nod.left = &nod2;
312  nod2 = *l;
313  nod2.left = &nod1;
314  nod2.complex = 1;
315  cgen(&nod, nn);
316 
317  return;
318  }
319  o = reg[REGARG];
320  gargs(r, &nod, &nod1);
321  if(l->addable < INDEXED) {
322  reglcgen(&nod, l, Z);
323  gopcode(OFUNC, Z, Z, &nod);
324  regfree(&nod);
325  } else
326  gopcode(OFUNC, Z, Z, l);
327  if(REGARG)
328  if(o != reg[REGARG])
329  reg[REGARG]--;
330  if(nn != Z) {
331  regret(&nod, n);
332  gopcode(OAS, &nod, Z, nn);
333  regfree(&nod);
334  }
335  break;
336 
337  case OIND:
338  if(nn == Z) {
339  cgen(l, nn);
340  break;
341  }
342  regialloc(&nod, n, nn);
343  r = l;
344  while(r->op == OADD)
345  r = r->right;
346  if(sconst(r)) {
347  v = r->vconst;
348  r->vconst = 0;
349  cgen(l, &nod);
350  nod.xoffset += v;
351  r->vconst = v;
352  } else
353  cgen(l, &nod);
354  regind(&nod, n);
355  gmove(&nod, nn);
356  regfree(&nod);
357  break;
358 
359  case OEQ:
360  case ONE:
361  case OLE:
362  case OLT:
363  case OGE:
364  case OGT:
365  case OLO:
366  case OLS:
367  case OHI:
368  case OHS:
369  if(nn == Z) {
370  nullwarn(l, r);
371  break;
372  }
373  boolgen(n, 1, nn);
374  break;
375 
376  case OANDAND:
377  case OOROR:
378  boolgen(n, 1, nn);
379  if(nn == Z)
380  patch(p, pc);
381  break;
382 
383  case ONOT:
384  if(nn == Z) {
385  nullwarn(l, Z);
386  break;
387  }
388  boolgen(n, 1, nn);
389  break;
390 
391  case OCOMMA:
392  cgen(l, Z);
393  cgen(r, nn);
394  break;
395 
396  case OCAST:
397  if(nn == Z) {
398  if(n->type != types[TVOID])
399  nullwarn(l, Z);
400  else
401  cgen(l, Z);
402  break;
403  }
404  /*
405  * convert from types l->n->nn
406  */
407  if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
408  /* both null, gen l->nn */
409  cgen(l, nn);
410  break;
411  }
412  if(typev[l->type->etype] || typev[n->type->etype]) {
413  cgen64(n, nn);
414  break;
415  }
416  regalloc(&nod, l, nn);
417  cgen(l, &nod);
418  regalloc(&nod1, n, &nod);
419  gmove(&nod, &nod1);
420  gmove(&nod1, nn);
421  regfree(&nod1);
422  regfree(&nod);
423  break;
424 
425  case ODOT:
426  sugen(l, nodrat, l->type->width);
427  if(nn != Z) {
428  warn(n, "non-interruptable temporary");
429  nod = *nodrat;
430  if(!r || r->op != OCONST) {
431  diag(n, "DOT and no offset");
432  break;
433  }
434  nod.xoffset += (long)r->vconst;
435  nod.type = n->type;
436  cgen(&nod, nn);
437  }
438  break;
439 
440  case OCOND:
441  bcgen(l, 1);
442  p1 = p;
443  cgen(r->left, nn);
444  gbranch(OGOTO);
445  patch(p1, pc);
446  p1 = p;
447  cgen(r->right, nn);
448  patch(p1, pc);
449  break;
450 
451  case OPOSTINC:
452  case OPOSTDEC:
453  v = 1;
454  if(l->type->etype == TIND)
455  v = l->type->link->width;
456  if(o == OPOSTDEC)
457  v = -v;
458  if(l->op == OBIT)
459  goto bitinc;
460  if(nn == Z)
461  goto pre;
462 
463  if(l->addable < INDEXED)
464  reglcgen(&nod2, l, Z);
465  else
466  nod2 = *l;
467 
468  regalloc(&nod, l, nn);
469  gopcode(OAS, &nod2, Z, &nod);
470  regalloc(&nod1, l, Z);
471  if(typefd[l->type->etype]) {
472  regalloc(&nod3, l, Z);
473  if(v < 0) {
474  gopcode(OAS, nodfconst(-v), Z, &nod3);
475  gopcode(OSUB, &nod3, &nod, &nod1);
476  } else {
477  gopcode(OAS, nodfconst(v), Z, &nod3);
478  gopcode(OADD, &nod3, &nod, &nod1);
479  }
480  regfree(&nod3);
481  } else
482  gopcode(OADD, nodconst(v), &nod, &nod1);
483  gopcode(OAS, &nod1, Z, &nod2);
484 
485  regfree(&nod);
486  regfree(&nod1);
487  if(l->addable < INDEXED)
488  regfree(&nod2);
489  break;
490 
491  case OPREINC:
492  case OPREDEC:
493  v = 1;
494  if(l->type->etype == TIND)
495  v = l->type->link->width;
496  if(o == OPREDEC)
497  v = -v;
498  if(l->op == OBIT)
499  goto bitinc;
500 
501  pre:
502  if(l->addable < INDEXED)
503  reglcgen(&nod2, l, Z);
504  else
505  nod2 = *l;
506 
507  regalloc(&nod, l, nn);
508  gopcode(OAS, &nod2, Z, &nod);
509  if(typefd[l->type->etype]) {
510  regalloc(&nod3, l, Z);
511  if(v < 0) {
512  gopcode(OAS, nodfconst(-v), Z, &nod3);
513  gopcode(OSUB, &nod3, Z, &nod);
514  } else {
515  gopcode(OAS, nodfconst(v), Z, &nod3);
516  gopcode(OADD, &nod3, Z, &nod);
517  }
518  regfree(&nod3);
519  } else
520  gopcode(OADD, nodconst(v), Z, &nod);
521  gopcode(OAS, &nod, Z, &nod2);
522  if(nn && l->op == ONAME) /* in x=++i, emit USED(i) */
523  gins(ANOP, l, Z);
524 
525  regfree(&nod);
526  if(l->addable < INDEXED)
527  regfree(&nod2);
528  break;
529 
530  bitinc:
531  if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
532  bitload(l, &nod, &nod1, &nod2, Z);
533  gopcode(OAS, &nod, Z, nn);
534  gopcode(OADD, nodconst(v), Z, &nod);
535  bitstore(l, &nod, &nod1, &nod2, Z);
536  break;
537  }
538  bitload(l, &nod, &nod1, &nod2, nn);
539  gopcode(OADD, nodconst(v), Z, &nod);
540  bitstore(l, &nod, &nod1, &nod2, nn);
541  break;
542  }
543  cursafe = curs;
544 }
545 
546 static void
547 genasop(int o, Node *l, Node *r, Node *nn)
548 {
549  Node nod, nod1, nod2;
550  int hardleft;
551 
552  hardleft = l->addable < INDEXED || l->complex >= FNX;
553  if(l->complex >= r->complex) {
554  if(hardleft)
555  reglcgen(&nod2, l, Z);
556  else
557  nod2 = *l;
558  regalloc(&nod1, r, Z);
559  cgen(r, &nod1);
560  } else {
561  regalloc(&nod1, r, Z);
562  cgen(r, &nod1);
563  if(hardleft)
564  reglcgen(&nod2, l, Z);
565  else
566  nod2 = *l;
567  }
568  if(nod1.type == nod2.type || !typefd[nod1.type->etype])
569  regalloc(&nod, &nod2, nn);
570  else
571  regalloc(&nod, &nod1, Z);
572  gmove(&nod2, &nod);
573  gopcode(o, &nod1, Z, &nod);
574  gmove(&nod, &nod2);
575  if(nn != Z)
576  gmove(&nod2, nn);
577  regfree(&nod);
578  regfree(&nod1);
579  if(hardleft)
580  regfree(&nod2);
581 }
582 
583 void
584 reglcgen(Node *t, Node *n, Node *nn)
585 {
586  Node *r;
587  long v;
588 
589  regialloc(t, n, nn);
590  if(n->op == OIND) {
591  r = n->left;
592  while(r->op == OADD)
593  r = r->right;
594  if(sconst(r)) {
595  v = r->vconst;
596  r->vconst = 0;
597  lcgen(n, t);
598  t->xoffset += v;
599  r->vconst = v;
600  regind(t, n);
601  return;
602  }
603  }
604  lcgen(n, t);
605  regind(t, n);
606 }
607 
608 void
609 lcgen(Node *n, Node *nn)
610 {
611  Prog *p1;
612  Node nod;
613 
614  if(debug['g']) {
615  prtree(nn, "lcgen lhs");
616  prtree(n, "lcgen");
617  }
618  if(n == Z || n->type == T)
619  return;
620  if(nn == Z) {
621  nn = &nod;
622  regalloc(&nod, n, Z);
623  }
624  switch(n->op) {
625  default:
626  if(n->addable < INDEXED) {
627  diag(n, "unknown op in lcgen: %O", n->op);
628  break;
629  }
630  nod = *n;
631  nod.op = OADDR;
632  nod.left = n;
633  nod.right = Z;
634  nod.type = types[TIND];
635  gopcode(OAS, &nod, Z, nn);
636  break;
637 
638  case OCOMMA:
639  cgen(n->left, n->left);
640  lcgen(n->right, nn);
641  break;
642 
643  case OIND:
644  cgen(n->left, nn);
645  break;
646 
647  case OCOND:
648  bcgen(n->left, 1);
649  p1 = p;
650  lcgen(n->right->left, nn);
651  gbranch(OGOTO);
652  patch(p1, pc);
653  p1 = p;
654  lcgen(n->right->right, nn);
655  patch(p1, pc);
656  break;
657  }
658 }
659 
660 void
661 bcgen(Node *n, int true)
662 {
663 
664  if(n->type == T)
665  gbranch(OGOTO);
666  else
667  boolgen(n, true, Z);
668 }
669 
670 void
671 boolgen(Node *n, int true, Node *nn)
672 {
673  int o, uns;
674  Prog *p1, *p2;
675  Node *l, *r, nod, nod1;
676  long curs;
677 
678  if(debug['g']) {
679  prtree(nn, "boolgen lhs");
680  prtree(n, "boolgen");
681  }
682  uns = 0;
683  curs = cursafe;
684  l = n->left;
685  r = n->right;
686  switch(n->op) {
687 
688  default:
689  if(n->op == OCONST) {
690  o = vconst(n);
691  if(!true)
692  o = !o;
693  gbranch(OGOTO);
694  if(o) {
695  p1 = p;
696  gbranch(OGOTO);
697  patch(p1, pc);
698  }
699  goto com;
700  }
701  if(typev[n->type->etype]) {
702  testv(n, true);
703  goto com;
704  }
705  regalloc(&nod, n, nn);
706  cgen(n, &nod);
707  o = ONE;
708  if(true)
709  o = comrel[relindex(o)];
710  if(typefd[n->type->etype]) {
711  nodreg(&nod1, n, NREG+FREGZERO);
712  gopcode(o, &nod, Z, &nod1);
713  } else
714  gopcode(o, &nod, Z, nodconst(0));
715  regfree(&nod);
716  goto com;
717 
718  case OCOMMA:
719  cgen(l, Z);
720  boolgen(r, true, nn);
721  break;
722 
723  case ONOT:
724  boolgen(l, !true, nn);
725  break;
726 
727  case OCOND:
728  bcgen(l, 1);
729  p1 = p;
730  bcgen(r->left, true);
731  p2 = p;
732  gbranch(OGOTO);
733  patch(p1, pc);
734  p1 = p;
735  bcgen(r->right, !true);
736  patch(p2, pc);
737  p2 = p;
738  gbranch(OGOTO);
739  patch(p1, pc);
740  patch(p2, pc);
741  goto com;
742 
743  case OANDAND:
744  if(!true)
745  goto caseor;
746 
747  caseand:
748  bcgen(l, true);
749  p1 = p;
750  bcgen(r, !true);
751  p2 = p;
752  patch(p1, pc);
753  gbranch(OGOTO);
754  patch(p2, pc);
755  goto com;
756 
757  case OOROR:
758  if(!true)
759  goto caseand;
760 
761  caseor:
762  bcgen(l, !true);
763  p1 = p;
764  bcgen(r, !true);
765  p2 = p;
766  gbranch(OGOTO);
767  patch(p1, pc);
768  patch(p2, pc);
769  goto com;
770 
771  case OHI:
772  case OHS:
773  case OLO:
774  case OLS:
775  uns = 1;
776  /* fall through */
777  case OEQ:
778  case ONE:
779  case OLE:
780  case OLT:
781  case OGE:
782  case OGT:
783  if(typev[l->type->etype]){
784  cmpv(n, true, Z);
785  goto com;
786  }
787  o = n->op;
788  if(true)
789  o = comrel[relindex(o)];
790  if(l->complex >= FNX && r->complex >= FNX) {
791  regret(&nod, r);
792  cgen(r, &nod);
793  regsalloc(&nod1, r);
794  gopcode(OAS, &nod, Z, &nod1);
795  regfree(&nod);
796  nod = *n;
797  nod.right = &nod1;
798  boolgen(&nod, true, nn);
799  break;
800  }
801  if(!uns && sconst(r) || (uns || o == OEQ || o == ONE) && uconst(r)) {
802  regalloc(&nod, l, nn);
803  cgen(l, &nod);
804  gopcode(o, &nod, Z, r);
805  regfree(&nod);
806  goto com;
807  }
808  if(l->complex >= r->complex) {
809  regalloc(&nod1, l, nn);
810  cgen(l, &nod1);
811  regalloc(&nod, r, Z);
812  cgen(r, &nod);
813  } else {
814  regalloc(&nod, r, nn);
815  cgen(r, &nod);
816  regalloc(&nod1, l, Z);
817  cgen(l, &nod1);
818  }
819  gopcode(o, &nod1, Z, &nod);
820  regfree(&nod);
821  regfree(&nod1);
822 
823  com:
824  if(nn != Z) {
825  p1 = p;
826  gopcode(OAS, nodconst(1L), Z, nn);
827  gbranch(OGOTO);
828  p2 = p;
829  patch(p1, pc);
830  gopcode(OAS, nodconst(0L), Z, nn);
831  patch(p2, pc);
832  }
833  break;
834  }
835  cursafe = curs;
836 }
837 
838 void
839 sugen(Node *n, Node *nn, long w)
840 {
841  Prog *p1;
842  Node nod0, nod1, nod2, nod3, nod4, *l, *r;
843  Type *t;
844  long pc1;
845  int i, m, c;
846 
847  if(n == Z || n->type == T)
848  return;
849  if(nn == nodrat)
850  if(w > nrathole)
851  nrathole = w;
852  if(debug['g']) {
853  prtree(nn, "sugen lhs");
854  prtree(n, "sugen");
855  }
856  if(typev[n->type->etype]) {
857  diag(n, "old vlong sugen: %O", n->op);
858  return;
859  }
860  switch(n->op) {
861  case OIND:
862  if(nn == Z) {
863  nullwarn(n->left, Z);
864  break;
865  }
866 
867  default:
868  goto copy;
869 
870  case ODOT:
871  l = n->left;
872  sugen(l, nodrat, l->type->width);
873  if(nn != Z) {
874  warn(n, "non-interruptable temporary");
875  nod1 = *nodrat;
876  r = n->right;
877  if(!r || r->op != OCONST) {
878  diag(n, "DOT and no offset");
879  break;
880  }
881  nod1.xoffset += (long)r->vconst;
882  nod1.type = n->type;
883  sugen(&nod1, nn, w);
884  }
885  break;
886 
887  case OSTRUCT:
888  /*
889  * rewrite so lhs has no side effects
890  */
891  if(nn != Z && side(nn)) {
892  nod1 = *n;
893  nod1.type = typ(TIND, n->type);
894  regalloc(&nod2, &nod1, Z);
895  lcgen(nn, &nod2);
896  regsalloc(&nod0, &nod1);
897  gopcode(OAS, &nod2, Z, &nod0);
898  regfree(&nod2);
899 
900  nod1 = *n;
901  nod1.op = OIND;
902  nod1.left = &nod0;
903  nod1.right = Z;
904  nod1.complex = 1;
905 
906  sugen(n, &nod1, w);
907  return;
908  }
909 
910  r = n->left;
911  for(t = n->type->link; t != T; t = t->down) {
912  l = r;
913  if(r->op == OLIST) {
914  l = r->left;
915  r = r->right;
916  }
917  if(nn == Z) {
918  cgen(l, nn);
919  continue;
920  }
921  /*
922  * hand craft *(&nn + o) = l
923  */
924  nod0 = znode;
925  nod0.op = OAS;
926  nod0.type = t;
927  nod0.left = &nod1;
928  nod0.right = l;
929 
930  nod1 = znode;
931  nod1.op = OIND;
932  nod1.type = t;
933  nod1.left = &nod2;
934 
935  nod2 = znode;
936  nod2.op = OADD;
937  nod2.type = typ(TIND, t);
938  nod2.left = &nod3;
939  nod2.right = &nod4;
940 
941  nod3 = znode;
942  nod3.op = OADDR;
943  nod3.type = nod2.type;
944  nod3.left = nn;
945 
946  nod4 = znode;
947  nod4.op = OCONST;
948  nod4.type = nod2.type;
949  nod4.vconst = t->offset;
950 
951  ccom(&nod0);
952  acom(&nod0);
953  xcom(&nod0);
954  nod0.addable = 0;
955 
956  /* prtree(&nod0, "hand craft"); /* */
957  cgen(&nod0, Z);
958  }
959  break;
960 
961  case OAS:
962  if(nn == Z) {
963  if(n->addable < INDEXED)
964  sugen(n->right, n->left, w);
965  break;
966  }
967  /* BOTCH -- functions can clobber rathole */
968  sugen(n->right, nodrat, w);
969  warn(n, "non-interruptable temporary");
970  sugen(nodrat, n->left, w);
971  sugen(nodrat, nn, w);
972  break;
973 
974  case OFUNC:
975  /* this transformation should probably be done earlier */
976  if(nn == Z) {
977  sugen(n, nodrat, w);
978  break;
979  }
980  if(nn->op != OIND) {
981  nn = new1(OADDR, nn, Z);
982  nn->type = types[TIND];
983  nn->addable = 0;
984  } else
985  nn = nn->left;
986  n = new(OFUNC, n->left, new(OLIST, nn, n->right));
987  n->complex = FNX;
988  n->type = types[TVOID];
989  n->left->type = types[TVOID];
990  cgen(n, Z);
991  break;
992 
993  case OCOND:
994  bcgen(n->left, 1);
995  p1 = p;
996  sugen(n->right->left, nn, w);
997  gbranch(OGOTO);
998  patch(p1, pc);
999  p1 = p;
1000  sugen(n->right->right, nn, w);
1001  patch(p1, pc);
1002  break;
1003 
1004  case OCOMMA:
1005  cgen(n->left, Z);
1006  sugen(n->right, nn, w);
1007  break;
1008  }
1009  return;
1010 
1011 copy:
1012  if(nn == Z)
1013  return;
1014  if(n->complex >= FNX && nn->complex >= FNX) {
1015  t = nn->type;
1016  nn->type = types[TLONG];
1017  regialloc(&nod1, nn, Z);
1018  lcgen(nn, &nod1);
1019  regsalloc(&nod2, &nod1);
1020  nn->type = t;
1021 
1022  gmove(&nod1, &nod2);
1023  regfree(&nod1);
1024 
1025  nod2.type = typ(TIND, t);
1026 
1027  nod1 = nod2;
1028  nod1.op = OIND;
1029  nod1.left = &nod2;
1030  nod1.right = Z;
1031  nod1.complex = 1;
1032  nod1.type = t;
1033 
1034  sugen(n, &nod1, w);
1035  return;
1036  }
1037 
1038  if(n->complex > nn->complex) {
1039  t = n->type;
1040  n->type = types[TLONG];
1041  reglcgen(&nod1, n, Z);
1042  n->type = t;
1043 
1044  t = nn->type;
1045  nn->type = types[TLONG];
1046  reglcgen(&nod2, nn, Z);
1047  nn->type = t;
1048  } else {
1049  t = nn->type;
1050  nn->type = types[TLONG];
1051  reglcgen(&nod2, nn, Z);
1052  nn->type = t;
1053 
1054  t = n->type;
1055  n->type = types[TLONG];
1056  reglcgen(&nod1, n, Z);
1057  n->type = t;
1058  }
1059 
1060  w /= SZ_LONG;
1061  if(w <= 5) {
1062  layout(&nod1, &nod2, w, 0, Z);
1063  goto out;
1064  }
1065 
1066  /*
1067  * minimize space for unrolling loop
1068  * 3,4,5 times. (6 or more is never minimum)
1069  * if small structure, try 2 also.
1070  */
1071  c = 0; /* set */
1072  m = 100;
1073  i = 3;
1074  if(w <= 15)
1075  i = 2;
1076  for(; i<=5; i++)
1077  if(i + w%i <= m) {
1078  c = i;
1079  m = c + w%c;
1080  }
1081 
1082  regalloc(&nod3, &regnode, Z);
1083  layout(&nod1, &nod2, w%c, w/c, &nod3);
1084 
1085  pc1 = pc;
1086  layout(&nod1, &nod2, c, 0, Z);
1087 
1088  gopcode(OSUB, nodconst(1L), Z, &nod3);
1089  nod1.op = OREGISTER;
1090  gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod1);
1091  nod2.op = OREGISTER;
1092  gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod2);
1093 
1094  gopcode(OGT, &nod3, Z, nodconst(0));
1095  patch(p, pc1);
1096 
1097  regfree(&nod3);
1098 out:
1099  regfree(&nod1);
1100  regfree(&nod2);
1101 }
1102 
1103 void
1104 layout(Node *f, Node *t, int c, int cv, Node *cn)
1105 {
1106  Node t1, t2;
1107 
1108  while(c > 3) {
1109  layout(f, t, 2, 0, Z);
1110  c -= 2;
1111  }
1112 
1113  regalloc(&t1, &regnode, Z);
1114  regalloc(&t2, &regnode, Z);
1115  if(c > 0) {
1116  gopcode(OAS, f, Z, &t1);
1117  f->xoffset += SZ_LONG;
1118  }
1119  if(cn != Z)
1120  gopcode(OAS, nodconst(cv), Z, cn);
1121  if(c > 1) {
1122  gopcode(OAS, f, Z, &t2);
1123  f->xoffset += SZ_LONG;
1124  }
1125  if(c > 0) {
1126  gopcode(OAS, &t1, Z, t);
1127  t->xoffset += SZ_LONG;
1128  }
1129  if(c > 2) {
1130  gopcode(OAS, f, Z, &t1);
1131  f->xoffset += SZ_LONG;
1132  }
1133  if(c > 1) {
1134  gopcode(OAS, &t2, Z, t);
1135  t->xoffset += SZ_LONG;
1136  }
1137  if(c > 2) {
1138  gopcode(OAS, &t1, Z, t);
1139  t->xoffset += SZ_LONG;
1140  }
1141  regfree(&t1);
1142  regfree(&t2);
1143 }
1144 
1145 /*
1146  * is the vlong's value directly addressible?
1147  */
1148 int
1149 isvdirect(Node *n)
1150 {
1151  return n->op == ONAME || n->op == OCONST || n->op == OINDREG;
1152 }
1153 
1154 /*
1155  * can the constant be used with given vlong op?
1156  */
1157 static int
1158 isvconstable(int o, vlong v)
1159 {
1160  switch(o) {
1161  case OADD:
1162  case OASADD:
1163  /* there isn't an immediate form for ADDE/SUBE, but there are special ADDME/ADDZE etc */
1164  return v == 0 || v == -1;
1165  case OAND:
1166  case OOR:
1167  case OXOR:
1168  case OLSHR:
1169  case OASHL:
1170  case OASHR:
1171  case OASLSHR:
1172  case OASASHL:
1173  case OASASHR:
1174  return 1;
1175  }
1176  return 0;
1177 }
1178 
1179 /*
1180  * most 64-bit operations: cgen into a register pair, then operate.
1181  * 64-bit comparisons are handled a little differently because the two underlying
1182  * comparisons can be compiled separately, since the calculations don't interact.
1183  */
1184 
1185 static void
1186 vcgen(Node *n, Node *o, int *f)
1187 {
1188  *f = 0;
1189  if(!isvdirect(n)) {
1190  if(n->complex >= FNX) {
1191  regsalloc(o, n);
1192  cgen(n, o);
1193  return;
1194  }
1195  *f = 1;
1196  if(n->addable < INDEXED && n->op != OIND && n->op != OINDEX) {
1197  regalloc(o, n, Z);
1198  cgen(n, o);
1199  } else
1200  reglcgen(o, n, Z);
1201  } else
1202  *o = *n;
1203 }
1204 
1205 static int
1206 isuns(int op)
1207 {
1208  switch(op){
1209  case OLO:
1210  case OLS:
1211  case OHI:
1212  case OHS:
1213  return 1;
1214  default:
1215  return 0;
1216  }
1217 }
1218 
1219 static void
1220 gcmpv(Node *l, Node *r, void (*mov)(Node*, Node*, int), int op)
1221 {
1222  Node vl, vr;
1223 
1224  regalloc(&vl, &regnode, Z);
1225  mov(l, &vl, 0);
1226  regalloc(&vr, &regnode, Z);
1227  mov(r, &vr, 1+isuns(op));
1228  gopcode(op, &vl, Z, &vr);
1229  if(vl.op == OREGISTER)
1230  regfree(&vl);
1231  if(vr.op == OREGISTER)
1232  regfree(&vr);
1233 }
1234 
1235 static void
1236 brcondv(Node *l, Node *r, int chi, int clo)
1237 {
1238  Prog *p1, *p2, *p3, *p4;
1239 
1240  gcmpv(l, r, gloadhi, chi);
1241  p1 = p;
1242  gins(ABNE, Z, Z);
1243  p2 = p;
1244  gcmpv(l, r, gloadlo, clo);
1245  p3 = p;
1246  gbranch(OGOTO);
1247  p4 = p;
1248  patch(p1, pc);
1249  patch(p3, pc);
1250  gbranch(OGOTO);
1251  patch(p2, pc);
1252  patch(p4, pc);
1253 }
1254 
1255 static void
1256 testv(Node *n, int true)
1257 {
1258  Node nod;
1259 
1260  nod = znode;
1261  nod.op = ONE;
1262  nod.left = n;
1263  nod.right = new1(0, Z, Z);
1264  *nod.right = *nodconst(0);
1265  nod.right->type = n->type;
1266  nod.type = types[TLONG];
1267  cmpv(&nod, true, Z);
1268 }
1269 
1270 /*
1271  * comparison for vlong does high and low order parts separately,
1272  * which saves loading the latter if the high order comparison suffices
1273  */
1274 static void
1275 cmpv(Node *n, int true, Node *nn)
1276 {
1277  Node *l, *r, nod, nod1;
1278  int o, f1, f2;
1279  Prog *p1, *p2;
1280  long curs;
1281 
1282  if(debug['g']) {
1283  if(nn != nil)
1284  prtree(nn, "cmpv lhs");
1285  prtree(n, "cmpv");
1286  }
1287  curs = cursafe;
1288  l = n->left;
1289  r = n->right;
1290  if(l->complex >= FNX && r->complex >= FNX) {
1291  regsalloc(&nod1, r);
1292  cgen(r, &nod1);
1293  nod = *n;
1294  nod.right = &nod1;
1295  cmpv(&nod, true, nn);
1296  cursafe = curs;
1297  return;
1298  }
1299  if(l->complex >= r->complex) {
1300  vcgen(l, &nod1, &f1);
1301  vcgen(r, &nod, &f2);
1302  } else {
1303  vcgen(r, &nod, &f2);
1304  vcgen(l, &nod1, &f1);
1305  }
1306  nod.type = types[TLONG];
1307  nod1.type = types[TLONG];
1308  o = n->op;
1309  if(true)
1310  o = comrel[relindex(o)];
1311  switch(o){
1312  case OEQ:
1313  gcmpv(&nod1, &nod, gloadhi, ONE);
1314  p1 = p;
1315  gcmpv(&nod1, &nod, gloadlo, ONE);
1316  p2 = p;
1317  gbranch(OGOTO);
1318  patch(p1, pc);
1319  patch(p2, pc);
1320  break;
1321  case ONE:
1322  gcmpv(&nod1, &nod, gloadhi, ONE);
1323  p1 = p;
1324  gcmpv(&nod1, &nod, gloadlo, OEQ);
1325  p2 = p;
1326  patch(p1, pc);
1327  gbranch(OGOTO);
1328  patch(p2, pc);
1329  break;
1330  case OLE:
1331  brcondv(&nod1, &nod, OLT, OLS);
1332  break;
1333  case OGT:
1334  brcondv(&nod1, &nod, OGT, OHI);
1335  break;
1336  case OLS:
1337  brcondv(&nod1, &nod, OLO, OLS);
1338  break;
1339  case OHI:
1340  brcondv(&nod1, &nod, OHI, OHI);
1341  break;
1342  case OLT:
1343  brcondv(&nod1, &nod, OLT, OLO);
1344  break;
1345  case OGE:
1346  brcondv(&nod1, &nod, OGT, OHS);
1347  break;
1348  case OLO:
1349  brcondv(&nod1, &nod, OLO, OLO);
1350  break;
1351  case OHS:
1352  brcondv(&nod1, &nod, OHI, OHS);
1353  break;
1354  default:
1355  diag(n, "bad cmpv");
1356  return;
1357  }
1358  if(f1)
1359  regfree(&nod1);
1360  if(f2)
1361  regfree(&nod);
1362  cursafe = curs;
1363 }
1364 
1365 static void
1366 cgen64(Node *n, Node *nn)
1367 {
1368  Node *l, *r, *d;
1369  Node nod, nod1;
1370  long curs;
1371  Type *t;
1372  int o, m;
1373 
1374  curs = cursafe;
1375  l = n->left;
1376  r = n->right;
1377  o = n->op;
1378  switch(o) {
1379 
1380  case OCONST:
1381  if(nn == Z) {
1382  nullwarn(n->left, Z);
1383  break;
1384  }
1385  if(nn->op != OREGPAIR) {
1386 //prtree(n, "cgen64 const");
1387  t = nn->type;
1388  nn->type = types[TLONG];
1389  reglcgen(&nod1, nn, Z);
1390  nn->type = t;
1391 
1392  if(align(0, types[TCHAR], Aarg1)) /* isbigendian */
1393  gmove(nod32const(n->vconst>>32), &nod1);
1394  else
1395  gmove(nod32const(n->vconst), &nod1);
1396  nod1.xoffset += SZ_LONG;
1397  if(align(0, types[TCHAR], Aarg1)) /* isbigendian */
1398  gmove(nod32const(n->vconst), &nod1);
1399  else
1400  gmove(nod32const(n->vconst>>32), &nod1);
1401 
1402  regfree(&nod1);
1403  } else
1404  gmove(n, nn);
1405  break;
1406 
1407  case OCAST:
1408  /*
1409  * convert from types l->n->nn
1410  */
1411  if(typev[l->type->etype]){
1412  /* vlong to non-vlong */
1413  if(!isvdirect(l)) {
1414  if(l->addable < INDEXED && l->op != OIND && l->op != OINDEX) {
1415  regalloc(&nod, l, l);
1416  cgen(l, &nod);
1417  regalloc(&nod1, n, nn);
1418  gmove(nod.right, &nod1);
1419  } else {
1420  reglcgen(&nod, l, Z);
1421  regalloc(&nod1, n, nn);
1422  gloadlo(&nod, &nod1, 0); /* TO DO: not correct for typefd */
1423  }
1424  regfree(&nod);
1425  } else {
1426  regalloc(&nod1, n, nn);
1427  gloadlo(l, &nod1, 0); /* TO DO: not correct for typefd */
1428  }
1429  }else{
1430  /* non-vlong to vlong */
1431  regalloc(&nod, l, Z);
1432  cgen(l, &nod);
1433  regalloc(&nod1, n, nn);
1434  gmove(&nod, nod1.right);
1435  if(typeu[l->type->etype])
1436  gmove(nodconst(0), nod1.left);
1437  else
1438  gopcode(OASHR, nodconst(31), nod1.right, nod1.left);
1439  regfree(&nod);
1440  }
1441  gmove(&nod1, nn);
1442  regfree(&nod1);
1443  break;
1444 
1445  case OFUNC:
1446  /* this transformation should probably be done earlier */
1447  if(nn == Z) {
1448  regsalloc(&nod1, n);
1449  nn = &nod1;
1450  }
1451  m = 0;
1452  if(nn->op != OIND) {
1453  if(nn->op == OREGPAIR) {
1454  m = 1;
1455  regsalloc(&nod1, nn);
1456  d = &nod1;
1457  }else
1458  d = nn;
1459  d = new1(OADDR, d, Z);
1460  d->type = types[TIND];
1461  d->addable = 0;
1462  } else
1463  d = nn->left;
1464  n = new(OFUNC, l, new(OLIST, d, r));
1465  n->complex = FNX;
1466  n->type = types[TVOID];
1467  n->left->type = types[TVOID];
1468  cgen(n, Z);
1469  if(m)
1470  gmove(&nod1, nn);
1471  break;
1472 
1473  default:
1474  diag(n, "bad cgen64 %O", o);
1475  break;
1476  }
1477  cursafe = curs;
1478 }