changelog shortlog tags branches changeset files revisions annotate raw help

Mercurial > hg > plan9front / sys/src/cmd/cc/pgen.c

changeset 6843: 7db92ee68f7e
parent: 5eeb36d3ddd0
author: 23hiro@gmail.com
date: Thu, 25 Oct 2018 08:09:10 +0200
permissions: -rw-r--r--
description: add Centrino Wireless-N 1030 (thanks lksmk from brazil)
1 #include "gc.h"
2 
3 void
4 codgen(Node *n, Node *nn)
5 {
6  Prog *sp;
7  Node *n1, nod, nod1;
8 
9  cursafe = 0;
10  curarg = 0;
11  maxargsafe = 0;
12  hasdoubled = 0;
13 
14  /*
15  * isolate name
16  */
17  for(n1 = nn;; n1 = n1->left) {
18  if(n1 == Z) {
19  diag(nn, "cant find function name");
20  return;
21  }
22  if(n1->op == ONAME)
23  break;
24  }
25  nearln = nn->lineno;
26  gpseudo(ATEXT, n1->sym, nodconst(stkoff));
27  sp = p;
28 
29  if(typecmplx[thisfn->link->etype]) {
30  if(nodret == nil) {
31  nodret = new(ONAME, Z, Z);
32  nodret->sym = slookup(".ret");
33  nodret->class = CPARAM;
34  nodret->type = types[TIND];
35  nodret->etype = TIND;
36  nodret = new(OIND, nodret, Z);
37  }
38  n1 = nodret->left;
39  if(n1->type == T || n1->type->link != thisfn->link) {
40  n1->type = typ(TIND, thisfn->link);
41  n1->etype = n1->type->etype;
42  nodret = new(OIND, n1, Z);
43  complex(nodret);
44  }
45  }
46 
47  /*
48  * isolate first argument
49  */
50  if(REGARG >= 0) {
51  if(typecmplx[thisfn->link->etype]) {
52  nod1 = *nodret->left;
53  nodreg(&nod, &nod1, REGARG);
54  gmove(&nod, &nod1);
55  } else
56  if(firstarg && typeword[firstargtype->etype]) {
57  nod1 = znode;
58  nod1.op = ONAME;
59  nod1.sym = firstarg;
60  nod1.type = firstargtype;
61  nod1.class = CPARAM;
62  nod1.xoffset = align(0, firstargtype, Aarg1);
63  nod1.etype = firstargtype->etype;
64  xcom(&nod1);
65  nodreg(&nod, &nod1, REGARG);
66  gmove(&nod, &nod1);
67  }
68  }
69 
70  canreach = 1;
71  warnreach = 1;
72  gen(n);
73  if(canreach && thisfn->link->etype != TVOID){
74  if(debug['B'])
75  warn(Z, "no return at end of function: %s", n1->sym->name);
76  else
77  diag(Z, "no return at end of function: %s", n1->sym->name);
78  }
79  noretval(3);
80  gbranch(ORETURN);
81 
82  if(!debug['N'] || debug['R'] || debug['P'])
83  regopt(sp);
84 
85  if(thechar=='6' || thechar=='7' || thechar=='9' || hasdoubled) /* [sic] */
86  maxargsafe = round(maxargsafe, 8);
87  sp->to.offset += maxargsafe;
88 }
89 
90 void
91 supgen(Node *n)
92 {
93  int owarn;
94  long spc;
95  Prog *sp;
96 
97  if(n == Z)
98  return;
99  suppress++;
100  owarn = warnreach;
101  warnreach = 0;
102  spc = pc;
103  sp = lastp;
104  gen(n);
105  lastp = sp;
106  pc = spc;
107  sp->link = nil;
108  suppress--;
109  warnreach = owarn;
110 }
111 
112 Node*
113 uncomma(Node *n)
114 {
115  while(n != Z && n->op == OCOMMA) {
116  cgen(n->left, Z);
117  n = n->right;
118  }
119  return n;
120 }
121 
122 void
123 gen(Node *n)
124 {
125  Node *l, nod, rn;
126  Prog *sp, *spc, *spb;
127  Case *cn;
128  long sbc, scc;
129  int snbreak, sncontin;
130  int f, o, oldreach;
131 
132 loop:
133  if(n == Z)
134  return;
135  nearln = n->lineno;
136  o = n->op;
137  if(debug['G'])
138  if(o != OLIST)
139  print("%L %O\n", nearln, o);
140 
141  if(!canreach) {
142  switch(o) {
143  case OLABEL:
144  case OCASE:
145  case OLIST:
146  case OCOMMA:
147  case OBREAK:
148  case OFOR:
149  case OWHILE:
150  case ODWHILE:
151  /* all handled specially - see switch body below */
152  break;
153  default:
154  if(warnreach) {
155  warn(n, "unreachable code %O", o);
156  warnreach = 0;
157  }
158  }
159  }
160 
161  switch(o) {
162 
163  default:
164  complex(n);
165  cgen(n, Z);
166  break;
167 
168  case OLIST:
169  case OCOMMA:
170  gen(n->left);
171 
172  rloop:
173  n = n->right;
174  goto loop;
175 
176  case ORETURN:
177  canreach = 0;
178  warnreach = !suppress;
179  complex(n);
180  if(n->type == T)
181  break;
182  l = uncomma(n->left);
183  if(l == Z) {
184  noretval(3);
185  gbranch(ORETURN);
186  break;
187  }
188  if(typecmplx[n->type->etype]) {
189  nod = znode;
190  nod.op = OAS;
191  nod.left = nodret;
192  nod.right = l;
193  nod.type = n->type;
194  nod.complex = l->complex;
195  cgen(&nod, Z);
196  noretval(3);
197  gbranch(ORETURN);
198  break;
199  }
200  if(newvlongcode && !typefd[n->type->etype]){
201  regret(&rn, n);
202  regfree(&rn);
203  nod = znode;
204  nod.op = OAS;
205  nod.left = &rn;
206  nod.right = l;
207  nod.type = n->type;
208  nod.complex = l->complex;
209  cgen(&nod, Z);
210  noretval(2);
211  gbranch(ORETURN);
212  break;
213  }
214  regret(&nod, n);
215  cgen(l, &nod);
216  regfree(&nod);
217  if(typefd[n->type->etype])
218  noretval(1);
219  else
220  noretval(2);
221  gbranch(ORETURN);
222  break;
223 
224  case OLABEL:
225  canreach = 1;
226  l = n->left;
227  if(l) {
228  l->pc = pc;
229  if(l->label)
230  patch(l->label, pc);
231  }
232  gbranch(OGOTO); /* prevent self reference in reg */
233  patch(p, pc);
234  goto rloop;
235 
236  case OGOTO:
237  canreach = 0;
238  warnreach = !suppress;
239  n = n->left;
240  if(n == Z)
241  return;
242  if(n->complex == 0) {
243  diag(Z, "label undefined: %s", n->sym->name);
244  return;
245  }
246  if(suppress)
247  return;
248  gbranch(OGOTO);
249  if(n->pc) {
250  patch(p, n->pc);
251  return;
252  }
253  if(n->label)
254  patch(n->label, pc-1);
255  n->label = p;
256  return;
257 
258  case OCASE:
259  canreach = 1;
260  l = n->left;
261  if(cases == C)
262  diag(n, "case/default outside a switch");
263  if(l == Z) {
264  casf();
265  cases->val = 0;
266  cases->def = 1;
267  cases->label = pc;
268  cases->isv = 0;
269  goto rloop;
270  }
271  complex(l);
272  if(l->type == T)
273  goto rloop;
274  if(l->op != OCONST || !typeswitch[l->type->etype]) {
275  diag(n, "case expression must be integer constant");
276  goto rloop;
277  }
278  casf();
279  cases->val = l->vconst;
280  cases->def = 0;
281  cases->label = pc;
282  cases->isv = typev[l->type->etype];
283  goto rloop;
284 
285  case OSWITCH:
286  l = n->left;
287  complex(l);
288  if(l->type == T)
289  break;
290  if(!typeswitch[l->type->etype]) {
291  diag(n, "switch expression must be integer");
292  break;
293  }
294 
295  gbranch(OGOTO); /* entry */
296  sp = p;
297 
298  cn = cases;
299  cases = C;
300  casf();
301 
302  sbc = breakpc;
303  breakpc = pc;
304  snbreak = nbreak;
305  nbreak = 0;
306  gbranch(OGOTO);
307  spb = p;
308 
309  gen(n->right); /* body */
310  if(canreach){
311  gbranch(OGOTO);
312  patch(p, breakpc);
313  nbreak++;
314  }
315 
316  patch(sp, pc);
317  regalloc(&nod, l, Z);
318  /* always signed */
319  if(typev[l->type->etype])
320  nod.type = types[TVLONG];
321  else
322  nod.type = types[TLONG];
323  cgen(l, &nod);
324  doswit(&nod);
325  regfree(&nod);
326  patch(spb, pc);
327 
328  cases = cn;
329  breakpc = sbc;
330  canreach = nbreak!=0;
331  if(canreach == 0)
332  warnreach = !suppress;
333  nbreak = snbreak;
334  break;
335 
336  case OWHILE:
337  case ODWHILE:
338  l = n->left;
339  gbranch(OGOTO); /* entry */
340  sp = p;
341 
342  scc = continpc;
343  continpc = pc;
344  gbranch(OGOTO);
345  spc = p;
346 
347  sbc = breakpc;
348  breakpc = pc;
349  snbreak = nbreak;
350  nbreak = 0;
351  gbranch(OGOTO);
352  spb = p;
353 
354  patch(spc, pc);
355  if(n->op == OWHILE)
356  patch(sp, pc);
357  bcomplex(l, Z); /* test */
358  patch(p, breakpc);
359  if(l->op != OCONST || vconst(l) == 0)
360  nbreak++;
361 
362  if(n->op == ODWHILE)
363  patch(sp, pc);
364  gen(n->right); /* body */
365  gbranch(OGOTO);
366  patch(p, continpc);
367 
368  patch(spb, pc);
369  continpc = scc;
370  breakpc = sbc;
371  canreach = nbreak!=0;
372  if(canreach == 0)
373  warnreach = !suppress;
374  nbreak = snbreak;
375  break;
376 
377  case OFOR:
378  l = n->left;
379  if(!canreach && l->right->left && warnreach) {
380  warn(n, "unreachable code FOR");
381  warnreach = 0;
382  }
383  gen(l->right->left); /* init */
384  gbranch(OGOTO); /* entry */
385  sp = p;
386 
387  /*
388  * if there are no incoming labels in the
389  * body and the top's not reachable, warn
390  */
391  if(!canreach && warnreach && deadheads(n)) {
392  warn(n, "unreachable code %O", o);
393  warnreach = 0;
394  }
395 
396  scc = continpc;
397  continpc = pc;
398  gbranch(OGOTO);
399  spc = p;
400 
401  sbc = breakpc;
402  breakpc = pc;
403  snbreak = nbreak;
404  nbreak = 0;
405  sncontin = ncontin;
406  ncontin = 0;
407  gbranch(OGOTO);
408  spb = p;
409 
410  patch(spc, pc);
411  gen(l->right->right); /* inc */
412  patch(sp, pc);
413  if(l->left != Z) { /* test */
414  bcomplex(l->left, Z);
415  patch(p, breakpc);
416  if(l->left->op != OCONST || vconst(l->left) == 0)
417  nbreak++;
418  }
419  canreach = 1;
420  gen(n->right); /* body */
421  if(canreach){
422  gbranch(OGOTO);
423  patch(p, continpc);
424  ncontin++;
425  }
426  if(!ncontin && l->right->right && warnreach) {
427  warn(l->right->right, "unreachable FOR inc");
428  warnreach = 0;
429  }
430 
431  patch(spb, pc);
432  continpc = scc;
433  breakpc = sbc;
434  canreach = nbreak!=0;
435  if(canreach == 0)
436  warnreach = !suppress;
437  nbreak = snbreak;
438  ncontin = sncontin;
439  break;
440 
441  case OCONTINUE:
442  if(continpc < 0) {
443  diag(n, "continue not in a loop");
444  break;
445  }
446  gbranch(OGOTO);
447  patch(p, continpc);
448  ncontin++;
449  canreach = 0;
450  warnreach = !suppress;
451  break;
452 
453  case OBREAK:
454  if(breakpc < 0) {
455  diag(n, "break not in a loop");
456  break;
457  }
458  /*
459  * Don't complain about unreachable break statements.
460  * There are breaks hidden in yacc's output and some people
461  * write return; break; in their switch statements out of habit.
462  * However, don't confuse the analysis by inserting an
463  * unreachable reference to breakpc either.
464  */
465  if(!canreach)
466  break;
467  gbranch(OGOTO);
468  patch(p, breakpc);
469  nbreak++;
470  canreach = 0;
471  warnreach = !suppress;
472  break;
473 
474  case OIF:
475  l = n->left;
476  if(bcomplex(l, n->right)) {
477  if(typefd[l->type->etype])
478  f = !l->fconst;
479  else
480  f = !l->vconst;
481  if(debug['c'])
482  print("%L const if %s\n", nearln, f ? "false" : "true");
483  if(f) {
484  canreach = 1;
485  supgen(n->right->left);
486  oldreach = canreach;
487  canreach = 1;
488  gen(n->right->right);
489  /*
490  * treat constant ifs as regular ifs for
491  * reachability warnings.
492  */
493  if(!canreach && oldreach && debug['w'] < 2)
494  warnreach = 0;
495  }
496  else {
497  canreach = 1;
498  gen(n->right->left);
499  oldreach = canreach;
500  canreach = 1;
501  supgen(n->right->right);
502  /*
503  * treat constant ifs as regular ifs for
504  * reachability warnings.
505  */
506  if(!oldreach && canreach && debug['w'] < 2)
507  warnreach = 0;
508  canreach = oldreach;
509  }
510  }
511  else {
512  sp = p;
513  canreach = 1;
514  if(n->right->left != Z)
515  gen(n->right->left);
516  oldreach = canreach;
517  canreach = 1;
518  if(n->right->right != Z) {
519  gbranch(OGOTO);
520  patch(sp, pc);
521  sp = p;
522  gen(n->right->right);
523  }
524  patch(sp, pc);
525  canreach = canreach || oldreach;
526  if(canreach == 0)
527  warnreach = !suppress;
528  }
529  break;
530 
531  case OSET:
532  case OUSED:
533  usedset(n->left, o);
534  break;
535  }
536 }
537 
538 void
539 usedset(Node *n, int o)
540 {
541  if(n->op == OLIST) {
542  usedset(n->left, o);
543  usedset(n->right, o);
544  return;
545  }
546  complex(n);
547  switch(n->op) {
548  case OADDR: /* volatile */
549  gins(ANOP, n, Z);
550  break;
551  case ONAME:
552  if(o == OSET)
553  gins(ANOP, Z, n);
554  else
555  gins(ANOP, n, Z);
556  break;
557  }
558 }
559 
560 int
561 bcomplex(Node *n, Node *c)
562 {
563  Node *b, nod;
564 
565 
566  complex(n);
567  if(n->type != T)
568  if(tcompat(n, T, n->type, tnot))
569  n->type = T;
570  if(n->type == T) {
571  gbranch(OGOTO);
572  return 0;
573  }
574  if(c != Z && n->op == OCONST && deadheads(c))
575  return 1;
576  /* this is not quite right yet, so ignore it for now */
577  if(0 && newvlongcode && typev[n->type->etype] && machcap(Z)) {
578  b = &nod;
579  b->op = ONE;
580  b->left = n;
581  b->right = new(0, Z, Z);
582  *b->right = *nodconst(0);
583  b->right->type = n->type;
584  b->type = types[TLONG];
585  cgen(b, Z);
586  return 0;
587  }
588  bool64(n);
589  boolgen(n, 1, Z);
590  return 0;
591 }