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
13 /*
14 * isolate name
15 */
16 for(n1 = nn;; n1 = n1->left) {
17 if(n1 == Z) {
18 diag(nn, "cant find function name");
19 return;
20 }
21 if(n1->op == ONAME)
22 break;
23 }
24 nearln = nn->lineno;
25 gpseudo(ATEXT, n1->sym, nodconst(stkoff));
26 sp = p;
27
28 /*
29 * isolate first argument
30 */
31 if(REGARG) {
32 if(typesu[thisfn->link->etype]) {
33 nod1 = *nodret->left;
34 nodreg(&nod, &nod1, REGARG);
35 gopcode(OAS, &nod, Z, &nod1);
36 } else
37 if(firstarg && typechlp[firstargtype->etype]) {
38 nod1 = *nodret->left;
39 nod1.sym = firstarg;
40 nod1.type = firstargtype;
41 nod1.xoffset = align(0, firstargtype, Aarg1);
42 nod1.etype = firstargtype->etype;
43 nodreg(&nod, &nod1, REGARG);
44 gopcode(OAS, &nod, Z, &nod1);
45 }
46 }
47
48 retok = 0;
49 gen(n);
50 if(!retok)
51 if(thisfn->link->etype != TVOID)
52 warn(Z, "no return at end of function: %s", n1->sym->name);
53 noretval(3);
54 gbranch(ORETURN);
55
56 if(!debug['N'] || debug['R'] || debug['P'])
57 regopt(sp);
58
59 sp->to.offset += maxargsafe;
60 }
61
62 void
gen(Node * n)63 gen(Node *n)
64 {
65 Node *l, nod;
66 Prog *sp, *spc, *spb;
67 Case *cn;
68 long sbc, scc;
69 int o;
70
71 loop:
72 if(n == Z)
73 return;
74 nearln = n->lineno;
75 o = n->op;
76 if(debug['G'])
77 if(o != OLIST)
78 print("%L %O\n", nearln, o);
79
80 retok = 0;
81 switch(o) {
82
83 default:
84 complex(n);
85 cgen(n, Z);
86 break;
87
88 case OLIST:
89 gen(n->left);
90
91 rloop:
92 n = n->right;
93 goto loop;
94
95 case ORETURN:
96 retok = 1;
97 complex(n);
98 if(n->type == T)
99 break;
100 l = n->left;
101 if(l == Z) {
102 noretval(3);
103 gbranch(ORETURN);
104 break;
105 }
106 if(typesu[n->type->etype]) {
107 sugen(l, nodret, n->type->width);
108 noretval(3);
109 gbranch(ORETURN);
110 break;
111 }
112 regret(&nod, n);
113 cgen(l, &nod);
114 regfree(&nod);
115 if(typefd[n->type->etype])
116 noretval(1);
117 else
118 noretval(2);
119 gbranch(ORETURN);
120 break;
121
122 case OLABEL:
123 l = n->left;
124 if(l) {
125 l->pc = pc;
126 if(l->label)
127 patch(l->label, pc);
128 }
129 gbranch(OGOTO); /* prevent self reference in reg */
130 patch(p, pc);
131 goto rloop;
132
133 case OGOTO:
134 retok = 1;
135 n = n->left;
136 if(n == Z)
137 return;
138 if(n->complex == 0) {
139 diag(Z, "label undefined: %s", n->sym->name);
140 return;
141 }
142 gbranch(OGOTO);
143 if(n->pc) {
144 patch(p, n->pc);
145 return;
146 }
147 if(n->label)
148 patch(n->label, pc-1);
149 n->label = p;
150 return;
151
152 case OCASE:
153 l = n->left;
154 if(cases == C)
155 diag(n, "case/default outside a switch");
156 if(l == Z) {
157 casf();
158 cases->val = 0;
159 cases->def = 1;
160 cases->label = pc;
161 goto rloop;
162 }
163 complex(l);
164 if(l->type == T)
165 goto rloop;
166 if(l->op == OCONST)
167 if(typechl[l->type->etype]) {
168 casf();
169 cases->val = l->vconst;
170 cases->def = 0;
171 cases->label = pc;
172 goto rloop;
173 }
174 diag(n, "case expression must be integer constant");
175 goto rloop;
176
177 case OSWITCH:
178 l = n->left;
179 complex(l);
180 if(l->type == T)
181 break;
182 if(!typechl[l->type->etype]) {
183 diag(n, "switch expression must be integer");
184 break;
185 }
186
187 gbranch(OGOTO); /* entry */
188 sp = p;
189
190 cn = cases;
191 cases = C;
192 casf();
193
194 sbc = breakpc;
195 breakpc = pc;
196 gbranch(OGOTO);
197 spb = p;
198
199 gen(n->right);
200 gbranch(OGOTO);
201 patch(p, breakpc);
202
203 patch(sp, pc);
204 regalloc(&nod, l, Z);
205 nod.type = types[TLONG];
206 cgen(l, &nod);
207 doswit(&nod);
208 regfree(&nod);
209 patch(spb, pc);
210
211 cases = cn;
212 breakpc = sbc;
213 break;
214
215 case OWHILE:
216 case ODWHILE:
217 l = n->left;
218 gbranch(OGOTO); /* entry */
219 sp = p;
220
221 scc = continpc;
222 continpc = pc;
223 gbranch(OGOTO);
224 spc = p;
225
226 sbc = breakpc;
227 breakpc = pc;
228 gbranch(OGOTO);
229 spb = p;
230
231 patch(spc, pc);
232 if(n->op == OWHILE)
233 patch(sp, pc);
234 bcomplex(l); /* test */
235 patch(p, breakpc);
236
237 if(n->op == ODWHILE)
238 patch(sp, pc);
239 gen(n->right); /* body */
240 gbranch(OGOTO);
241 patch(p, continpc);
242
243 patch(spb, pc);
244 continpc = scc;
245 breakpc = sbc;
246 break;
247
248 case OFOR:
249 l = n->left;
250 gen(l->right->left); /* init */
251 gbranch(OGOTO); /* entry */
252 sp = p;
253
254 scc = continpc;
255 continpc = pc;
256 gbranch(OGOTO);
257 spc = p;
258
259 sbc = breakpc;
260 breakpc = pc;
261 gbranch(OGOTO);
262 spb = p;
263
264 patch(spc, pc);
265 gen(l->right->right); /* inc */
266 patch(sp, pc);
267 if(l->left != Z) { /* test */
268 bcomplex(l->left);
269 patch(p, breakpc);
270 }
271 gen(n->right); /* body */
272 gbranch(OGOTO);
273 patch(p, continpc);
274
275 patch(spb, pc);
276 continpc = scc;
277 breakpc = sbc;
278 break;
279
280 case OCONTINUE:
281 if(continpc < 0) {
282 diag(n, "continue not in a loop");
283 break;
284 }
285 gbranch(OGOTO);
286 patch(p, continpc);
287 break;
288
289 case OBREAK:
290 if(breakpc < 0) {
291 diag(n, "break not in a loop");
292 break;
293 }
294 gbranch(OGOTO);
295 patch(p, breakpc);
296 break;
297
298 case OIF:
299 l = n->left;
300 bcomplex(l);
301 sp = p;
302 if(n->right->left != Z)
303 gen(n->right->left);
304 if(n->right->right != Z) {
305 gbranch(OGOTO);
306 patch(sp, pc);
307 sp = p;
308 gen(n->right->right);
309 }
310 patch(sp, pc);
311 break;
312
313 case OSET:
314 case OUSED:
315 usedset(n->left, o);
316 break;
317 }
318 }
319
320 void
usedset(Node * n,int o)321 usedset(Node *n, int o)
322 {
323 if(n->op == OLIST) {
324 usedset(n->left, o);
325 usedset(n->right, o);
326 return;
327 }
328 complex(n);
329 switch(n->op) {
330 case OADDR: /* volatile */
331 gins(ANOP, n, Z);
332 break;
333 case ONAME:
334 if(o == OSET)
335 gins(ANOP, Z, n);
336 else
337 gins(ANOP, n, Z);
338 break;
339 }
340 }
341
342 void
noretval(int n)343 noretval(int n)
344 {
345
346 if(n & 1) {
347 gins(ANOP, Z, Z);
348 p->to.type = D_REG;
349 p->to.reg = REGRET;
350 }
351 if(n & 2) {
352 gins(ANOP, Z, Z);
353 p->to.type = D_FREG;
354 p->to.reg = FREGRET;
355 }
356 }
357
358 /*
359 * calculate addressability as follows
360 * CONST ==> 20 $value
361 * NAME ==> 10 name
362 * REGISTER ==> 11 register
363 * INDREG ==> 12 *[(reg)+offset]
364 * &10 ==> 2 $name
365 * ADD(2, 20) ==> 2 $name+offset
366 * ADD(3, 20) ==> 3 $(reg)+offset
367 * &12 ==> 3 $(reg)+offset
368 * *11 ==> 11 ??
369 * *2 ==> 10 name
370 * *3 ==> 12 *(reg)+offset
371 * calculate complexity (number of registers)
372 */
373 void
xcom(Node * n)374 xcom(Node *n)
375 {
376 Node *l, *r;
377 int t;
378
379 if(n == Z)
380 return;
381 l = n->left;
382 r = n->right;
383 n->addable = 0;
384 n->complex = 0;
385 switch(n->op) {
386 case OCONST:
387 n->addable = 20;
388 return;
389
390 case OREGISTER:
391 n->addable = 11;
392 return;
393
394 case OINDREG:
395 n->addable = 12;
396 return;
397
398 case ONAME:
399 n->addable = 10;
400 return;
401
402 case OADDR:
403 xcom(l);
404 if(l->addable == 10)
405 n->addable = 2;
406 if(l->addable == 12)
407 n->addable = 3;
408 break;
409
410 case OIND:
411 xcom(l);
412 if(l->addable == 11)
413 n->addable = 12;
414 if(l->addable == 3)
415 n->addable = 12;
416 if(l->addable == 2)
417 n->addable = 10;
418 break;
419
420 case OADD:
421 xcom(l);
422 xcom(r);
423 if(l->addable == 20) {
424 if(r->addable == 2)
425 n->addable = 2;
426 if(r->addable == 3)
427 n->addable = 3;
428 }
429 if(r->addable == 20) {
430 if(l->addable == 2)
431 n->addable = 2;
432 if(l->addable == 3)
433 n->addable = 3;
434 }
435 break;
436
437 case OASLMUL:
438 case OASMUL:
439 xcom(l);
440 xcom(r);
441 t = vlog(r);
442 if(t >= 0) {
443 n->op = OASASHL;
444 r->vconst = t;
445 r->type = types[TINT];
446 }
447 break;
448
449 case OMUL:
450 case OLMUL:
451 xcom(l);
452 xcom(r);
453 t = vlog(r);
454 if(t >= 0) {
455 n->op = OASHL;
456 r->vconst = t;
457 r->type = types[TINT];
458 }
459 t = vlog(l);
460 if(t >= 0) {
461 n->op = OASHL;
462 n->left = r;
463 n->right = l;
464 r = l;
465 l = n->left;
466 r->vconst = t;
467 r->type = types[TINT];
468 }
469 break;
470
471 case OASLDIV:
472 xcom(l);
473 xcom(r);
474 t = vlog(r);
475 if(t >= 0) {
476 n->op = OASLSHR;
477 r->vconst = t;
478 r->type = types[TINT];
479 }
480 break;
481
482 case OLDIV:
483 xcom(l);
484 xcom(r);
485 t = vlog(r);
486 if(t >= 0) {
487 n->op = OLSHR;
488 r->vconst = t;
489 r->type = types[TINT];
490 }
491 break;
492
493 case OASLMOD:
494 xcom(l);
495 xcom(r);
496 t = vlog(r);
497 if(t >= 0) {
498 n->op = OASAND;
499 r->vconst--;
500 }
501 break;
502
503 case OLMOD:
504 xcom(l);
505 xcom(r);
506 t = vlog(r);
507 if(t >= 0) {
508 n->op = OAND;
509 r->vconst--;
510 }
511 break;
512
513 default:
514 if(l != Z)
515 xcom(l);
516 if(r != Z)
517 xcom(r);
518 break;
519 }
520 if(n->addable >= 10)
521 return;
522
523 if(l != Z)
524 n->complex = l->complex;
525 if(r != Z) {
526 if(r->complex == n->complex)
527 n->complex = r->complex+1;
528 else
529 if(r->complex > n->complex)
530 n->complex = r->complex;
531 }
532 if(n->complex == 0)
533 n->complex++;
534
535 switch(n->op) {
536 case OFUNC:
537 n->complex = FNX;
538 break;
539
540 case OADD:
541 case OXOR:
542 case OAND:
543 case OOR:
544 case OEQ:
545 case ONE:
546 /*
547 * immediate operators, make const on right
548 */
549 if(l->op == OCONST) {
550 n->left = r;
551 n->right = l;
552 }
553 break;
554 }
555 }
556
557 void
bcomplex(Node * n)558 bcomplex(Node *n)
559 {
560
561 complex(n);
562 if(n->type != T)
563 if(tcompat(n, T, n->type, tnot))
564 n->type = T;
565 if(n->type != T)
566 boolgen(n, 1, Z);
567 else
568 gbranch(OGOTO);
569 }
570