changelog shortlog tags branches changeset files revisions annotate raw help

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

changeset 7169: 94fca26a23d8
parent: 1c857cff1d86
child: b3b84087ac92
author: cinap_lenrek@felloff.net
date: Wed, 17 Apr 2019 23:38:00 +0200
permissions: -rw-r--r--
description: 7c: fix long to vlong/pointer conversion, avoid negative immediate offsets

we have to explicitely convert to vlong by sign or
zero extending as not every operation leaves a proper
zero/sign extended result in the register. for example
NEGW will zero extend, breaking negative int offsets
on pointers.

we explicitely insert SXTW or MOVWU instructions which
the peephole optimizer takes out again when it is safe
todo so.

when promoting constant offsets to immediate offsets,
make sure the offset will be in range. otherwise the
linker will produce not so optimal pointer arithmetic
instructions to calculate the offset.
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, nn);
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 }