1 #include "gc.h"
2
3 void
codgen(Node * n,Node * nn)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
supgen(Node * n)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*
uncomma(Node * n)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
gen(Node * n)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
usedset(Node * n,int o)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
bcomplex(Node * n,Node * c)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 }
592