Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
}