changelog shortlog tags branches changeset files revisions annotate raw help

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

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