changelog shortlog tags branches changeset files revisions annotate raw help

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