1 #include "c.h"
2 
3 
4 #define iscall(op) (generic(op) == CALL \
5 	|| (IR->mulops_calls \
6 	&& (generic(op)==DIV||generic(op)==MOD||generic(op)==MUL) \
7 	&& ( optype(op)==U  || optype(op)==I)))
8 static Node forest;
9 static struct dag {
10 	struct node node;
11 	struct dag *hlink;
12 } *buckets[16];
13 int nodecount;
14 static Tree firstarg;
15 int assignargs = 1;
16 int prunetemps = -1;
17 static Node *tail;
18 
19 static int depth = 0;
20 static Node replace(Node);
21 static Node prune(Node);
22 static Node asgnnode(Symbol, Node);
23 static struct dag *dagnode(int, Node, Node, Symbol);
24 static Symbol equated(Symbol);
25 static void fixup(Node);
26 static void labelnode(int);
27 static void list(Node);
28 static void kill(Symbol);
29 static Node node(int, Node, Node, Symbol);
30 static void printdag1(Node, int, int);
31 static void printnode(Node, int, int);
32 static void reset(void);
33 static Node tmpnode(Node);
34 static void typestab(Symbol, void *);
35 static Node undag(Node);
36 static Node visit(Node, int);
37 static void unlist(void);
walk(Tree tp,int tlab,int flab)38 void walk(Tree tp, int tlab, int flab) {
39 	listnodes(tp, tlab, flab);
40 	if (forest) {
41 		Node list = forest->link;
42 		forest->link = NULL;
43 		if (!IR->wants_dag)
44 			list = undag(list);
45 		code(Gen)->u.forest = list;
46 		forest = NULL;
47 	}
48 	reset();
49 	deallocate(STMT);
50 }
51 
node(int op,Node l,Node r,Symbol sym)52 static Node node(int op, Node l, Node r, Symbol sym) {
53 	int i;
54 	struct dag *p;
55 
56 	i = (opindex(op)^((unsigned long)sym>>2))&(NELEMS(buckets)-1);
57 	for (p = buckets[i]; p; p = p->hlink)
58 		if (p->node.op      == op && p->node.syms[0] == sym
59 		&&  p->node.kids[0] == l  && p->node.kids[1] == r)
60 			return &p->node;
61 	p = dagnode(op, l, r, sym);
62 	p->hlink = buckets[i];
63 	buckets[i] = p;
64 	++nodecount;
65 	return &p->node;
66 }
dagnode(int op,Node l,Node r,Symbol sym)67 static struct dag *dagnode(int op, Node l, Node r, Symbol sym) {
68 	struct dag *p;
69 
70 	NEW0(p, FUNC);
71 	p->node.op = op;
72 	if ((p->node.kids[0] = l) != NULL)
73 		++l->count;
74 	if ((p->node.kids[1] = r) != NULL)
75 		++r->count;
76 	p->node.syms[0] = sym;
77 	return p;
78 }
newnode(int op,Node l,Node r,Symbol sym)79 Node newnode(int op, Node l, Node r, Symbol sym) {
80 	return &dagnode(op, l, r, sym)->node;
81 }
kill(Symbol p)82 static void kill(Symbol p) {
83 	int i;
84 	struct dag **q;
85 
86 	for (i = 0; i < NELEMS(buckets); i++)
87 		for (q = &buckets[i]; *q; )
88 			if (generic((*q)->node.op) == INDIR &&
89 			    (!isaddrop((*q)->node.kids[0]->op)
90 			     || (*q)->node.kids[0]->syms[0] == p)) {
91 				*q = (*q)->hlink;
92 				--nodecount;
93 			} else
94 				q = &(*q)->hlink;
95 }
reset(void)96 static void reset(void) {
97 	if (nodecount > 0)
98 		memset(buckets, 0, sizeof buckets);
99 	nodecount = 0;
100 }
listnodes(Tree tp,int tlab,int flab)101 Node listnodes(Tree tp, int tlab, int flab) {
102 	Node p = NULL, l, r;
103 	int op;
104 
105 	assert(tlab || flab || (tlab == 0 && flab == 0));
106 	if (tp == NULL)
107 		return NULL;
108 	if (tp->node)
109 		return tp->node;
110 	op = tp->op + sizeop(tp->type->size);
111 	switch (generic(tp->op)) {
112 	case AND:   { if (depth++ == 0) reset();
113 		      if (flab) {
114 		      	listnodes(tp->kids[0], 0, flab);
115 		      	listnodes(tp->kids[1], 0, flab);
116 		      } else {
117 		      	listnodes(tp->kids[0], 0, flab = genlabel(1));
118 		      	listnodes(tp->kids[1], tlab, 0);
119 		      	labelnode(flab);
120 		      }
121 		      depth--; } break;
122 	case OR:    { if (depth++ == 0)
123 		      	reset();
124 		      if (tlab) {
125 		      	listnodes(tp->kids[0], tlab, 0);
126 		      	listnodes(tp->kids[1], tlab, 0);
127 		      } else {
128 		      	tlab = genlabel(1);
129 		      	listnodes(tp->kids[0], tlab, 0);
130 		      	listnodes(tp->kids[1], 0, flab);
131 		      	labelnode(tlab);
132 		      }
133 		      depth--;
134  } break;
135 	case NOT:   { return listnodes(tp->kids[0], flab, tlab); }
136 	case COND:  { Tree q = tp->kids[1];
137 		      assert(tlab == 0 && flab == 0);
138 		      if (tp->u.sym)
139 		      	addlocal(tp->u.sym);
140 		      flab = genlabel(2);
141 		      listnodes(tp->kids[0], 0, flab);
142 		      assert(q && q->op == RIGHT);
143 		      reset();
144 		      listnodes(q->kids[0], 0, 0);
145 		      if (forest->op == LABEL+V) {
146 		      	equatelab(forest->syms[0], findlabel(flab + 1));
147 		      	unlist();
148 		      }
149 		      list(jump(flab + 1));
150 		      labelnode(flab);
151 		      listnodes(q->kids[1], 0, 0);
152 		      if (forest->op == LABEL+V) {
153 		      	equatelab(forest->syms[0], findlabel(flab + 1));
154 		      	unlist();
155 		      }
156 		      labelnode(flab + 1);
157 
158 		      if (tp->u.sym)
159 		      	p = listnodes(idtree(tp->u.sym), 0, 0); } break;
160 	case CNST:  { Type ty = unqual(tp->type);
161 		      assert(ty->u.sym);
162 		      if (tlab || flab) {
163 		      	assert(ty == inttype);
164 		      	if (tlab && tp->u.v.i != 0)
165 		      		list(jump(tlab));
166 		      	else if (flab && tp->u.v.i == 0)
167 		      		list(jump(flab));
168 		      }
169 		      else if (ty->u.sym->addressed)
170 		      	p = listnodes(cvtconst(tp), 0, 0);
171 		      else
172 		      	p = node(op, NULL, NULL, constant(ty, tp->u.v)); } break;
173 	case RIGHT: { if (   tp->kids[0] && tp->kids[1]
174 			  &&  generic(tp->kids[1]->op) == ASGN
175 			  && ((generic(tp->kids[0]->op) == INDIR
176 			  && tp->kids[0]->kids[0] == tp->kids[1]->kids[0])
177 			  || (tp->kids[0]->op == FIELD
178 			  &&  tp->kids[0] == tp->kids[1]->kids[0]))) {
179 		      	assert(tlab == 0 && flab == 0);
180 			if (generic(tp->kids[0]->op) == INDIR) {
181 				p = listnodes(tp->kids[0], 0, 0);
182 				list(p);
183 				listnodes(tp->kids[1], 0, 0);
184 			}
185 			else {
186 				assert(generic(tp->kids[0]->kids[0]->op) == INDIR);
187 				list(listnodes(tp->kids[0]->kids[0], 0, 0));
188 				p = listnodes(tp->kids[0], 0, 0);
189 				listnodes(tp->kids[1], 0, 0);
190 			}
191 		      } else if (tp->kids[1]) {
192 		      	listnodes(tp->kids[0], 0, 0);
193 		      	p = listnodes(tp->kids[1], tlab, flab);
194 		      } else
195 		      	p = listnodes(tp->kids[0], tlab, flab); } break;
196 	case JUMP:  { assert(tlab == 0 && flab == 0);
197 		      assert(tp->u.sym == 0);
198 		      assert(tp->kids[0]);
199 		      l = listnodes(tp->kids[0], 0, 0);
200 		      list(newnode(JUMP+V, l, NULL, NULL));
201 		      reset(); } break;
202 	case CALL:  { Tree save = firstarg;
203 		      firstarg = NULL;
204 		      assert(tlab == 0 && flab == 0);
205 		      if (tp->op == CALL+B && !IR->wants_callb) {
206 		      	Tree arg0 = tree(ARG+P, tp->kids[1]->type,
207 				tp->kids[1], NULL);
208 			if (IR->left_to_right)
209 				firstarg = arg0;
210 			l = listnodes(tp->kids[0], 0, 0);
211 			if (!IR->left_to_right || firstarg) {
212 				firstarg = NULL;
213 				listnodes(arg0, 0, 0);
214 			}
215 		      	p = newnode(CALL+V, l, NULL, NULL);
216 		      } else {
217 		      	l = listnodes(tp->kids[0], 0, 0);
218 		      	r = listnodes(tp->kids[1], 0, 0);
219 		      	p = newnode(tp->op == CALL+B ? tp->op : op, l, r, NULL);
220 		      }
221 		      NEW0(p->syms[0], FUNC);
222 		      assert(isptr(tp->kids[0]->type));
223 		      assert(isfunc(tp->kids[0]->type->type));
224 		      p->syms[0]->type = tp->kids[0]->type->type;
225 		      list(p);
226 		      reset();
227 		      cfunc->u.f.ncalls++;
228 		      firstarg = save;
229  } break;
230 	case ARG:   { assert(tlab == 0 && flab == 0);
231 		      if (IR->left_to_right)
232 		      	listnodes(tp->kids[1], 0, 0);
233 		      if (firstarg) {
234 		      	Tree arg = firstarg;
235 		      	firstarg = NULL;
236 		      	listnodes(arg, 0, 0);
237 		      }
238 		      l = listnodes(tp->kids[0], 0, 0);
239 		      list(newnode(tp->op == ARG+B ? tp->op : op, l, NULL, NULL));
240 		      forest->syms[0] = intconst(tp->type->size);
241 		      forest->syms[1] = intconst(tp->type->align);
242 		      if (!IR->left_to_right)
243 		      	listnodes(tp->kids[1], 0, 0); } break;
244 	case EQ:  case NE: case GT: case GE: case LE:
245 	case LT:    { assert(tp->u.sym == 0);
246 		      assert(errcnt || tlab || flab);
247 		      l = listnodes(tp->kids[0], 0, 0);
248 		      r = listnodes(tp->kids[1], 0, 0);
249 		      assert(errcnt || opkind(l->op) == opkind(r->op));
250 		      assert(errcnt || optype(op) == optype(l->op));
251 		      if (tlab)
252 		      	assert(flab == 0),
253 		      	list(newnode(generic(tp->op) + opkind(l->op), l, r, findlabel(tlab)));
254 		      else if (flab) {
255 		      	switch (generic(tp->op)) {
256 		      	case EQ: op = NE; break;
257 		      	case NE: op = EQ; break;
258 		      	case GT: op = LE; break;
259 		      	case LT: op = GE; break;
260 		      	case GE: op = LT; break;
261 		      	case LE: op = GT; break;
262 		      	default: assert(0);
263 		      	}
264 		      	list(newnode(op + opkind(l->op), l, r, findlabel(flab)));
265 		      }
266 		      if (forest && forest->syms[0])
267 		      	forest->syms[0]->ref++; } break;
268 	case ASGN:  { assert(tlab == 0 && flab == 0);
269 		      if (tp->kids[0]->op == FIELD) {
270 		      	Tree  x = tp->kids[0]->kids[0];
271 			Field f = tp->kids[0]->u.field;
272 			assert(generic(x->op) == INDIR);
273 			reset();
274 			l = listnodes(lvalue(x), 0, 0);
275 			if (fieldsize(f) < 8*f->type->size) {
276 				unsigned int fmask = fieldmask(f);
277 				unsigned int  mask = fmask<<fieldright(f);
278 				Tree q = tp->kids[1];
279 				if ((q->op == CNST+I && q->u.v.i == 0)
280 				||  (q->op == CNST+U && q->u.v.u == 0))
281 					q = bittree(BAND, x, cnsttree(unsignedtype, (unsigned long)~mask));
282 				else if ((q->op == CNST+I && (q->u.v.i&fmask) == fmask)
283 				||       (q->op == CNST+U && (q->u.v.u&fmask) == fmask))
284 					q = bittree(BOR, x, cnsttree(unsignedtype, (unsigned long)mask));
285 				else {
286 					listnodes(q, 0, 0);
287 					q = bittree(BOR,
288 						bittree(BAND, rvalue(lvalue(x)),
289 							cnsttree(unsignedtype, (unsigned long)~mask)),
290 						bittree(BAND, shtree(LSH, cast(q, unsignedtype),
291 							cnsttree(unsignedtype, (unsigned long)fieldright(f))),
292 							cnsttree(unsignedtype, (unsigned long)mask)));
293 				}
294 				r = listnodes(q, 0, 0);
295 				op = ASGN + ttob(q->type);
296 			} else {
297 				r = listnodes(tp->kids[1], 0, 0);
298 				op = ASGN + ttob(tp->kids[1]->type);
299 			}
300 		      } else {
301 		      	l = listnodes(tp->kids[0], 0, 0);
302 		      	r = listnodes(tp->kids[1], 0, 0);
303 		      }
304 		      list(newnode(tp->op == ASGN+B ? tp->op : op, l, r, NULL));
305 		      forest->syms[0] = intconst(tp->kids[1]->type->size);
306 		      forest->syms[1] = intconst(tp->kids[1]->type->align);
307 		      if (isaddrop(tp->kids[0]->op)
308 		      && !tp->kids[0]->u.sym->computed)
309 		      	kill(tp->kids[0]->u.sym);
310 		      else
311 		      	reset();
312 		      p = listnodes(tp->kids[1], 0, 0); } break;
313 	case BOR: case BAND: case BXOR:
314 	case ADD: case SUB:  case RSH:
315 	case LSH:   { assert(tlab == 0 && flab == 0);
316 		      l = listnodes(tp->kids[0], 0, 0);
317 		      r = listnodes(tp->kids[1], 0, 0);
318 		      p = node(op, l, r, NULL); } break;
319 	case DIV: case MUL:
320 	case MOD:   { assert(tlab == 0 && flab == 0);
321 		      l = listnodes(tp->kids[0], 0, 0);
322 		      r = listnodes(tp->kids[1], 0, 0);
323 		      p = node(op, l, r, NULL);
324 		      if (IR->mulops_calls && isint(tp->type)) {
325 		      	list(p);
326 		      	cfunc->u.f.ncalls++;
327 		      } } break;
328 	case RET:   { assert(tlab == 0 && flab == 0);
329 		      l = listnodes(tp->kids[0], 0, 0);
330 		      list(newnode(op, l, NULL, NULL)); } break;
331 	case CVF: case CVI: case CVP:
332 	case CVU:   { assert(tlab == 0 && flab == 0);
333 		      assert(optype(tp->kids[0]->op) != optype(tp->op) || tp->kids[0]->type->size != tp->type->size);
334 		      l = listnodes(tp->kids[0], 0, 0);
335 		      p = node(op, l, NULL, intconst(tp->kids[0]->type->size));
336  } break;
337 	case BCOM:
338 	case NEG:   { assert(tlab == 0 && flab == 0);
339 		      l = listnodes(tp->kids[0], 0, 0);
340 		      p = node(op, l, NULL, NULL); } break;
341 	case INDIR: { Type ty = tp->kids[0]->type;
342 		      assert(tlab == 0 && flab == 0);
343 		      l = listnodes(tp->kids[0], 0, 0);
344 		      if (isptr(ty))
345 		      	ty = unqual(ty)->type;
346 		      if (isvolatile(ty)
347 		      || (isstruct(ty) && unqual(ty)->u.sym->u.s.vfields))
348 		      	p = newnode(tp->op == INDIR+B ? tp->op : op, l, NULL, NULL);
349 		      else
350 		      	p = node(tp->op == INDIR+B ? tp->op : op, l, NULL, NULL); } break;
351 	case FIELD: { Tree q = tp->kids[0];
352 		      if (tp->type == inttype) {
353 		      	long n = fieldleft(tp->u.field);
354 		      	q = shtree(RSH,
355 		      		shtree(LSH, q, cnsttree(inttype, n)),
356 		      		cnsttree(inttype, n + fieldright(tp->u.field)));
357 		      } else if (fieldsize(tp->u.field) < 8*tp->u.field->type->size)
358 		      	q = bittree(BAND,
359 		      		shtree(RSH, q, cnsttree(inttype, (long)fieldright(tp->u.field))),
360 		      		cnsttree(unsignedtype, (unsigned long)fieldmask(tp->u.field)));
361 		      assert(tlab == 0 && flab == 0);
362 		      p = listnodes(q, 0, 0); } break;
363 	case ADDRG:
364 	case ADDRF: { assert(tlab == 0 && flab == 0);
365 		      p = node(tp->op + sizeop(voidptype->size), NULL, NULL, tp->u.sym);
366  } break;
367 	case ADDRL: { assert(tlab == 0 && flab == 0);
368 		      if (tp->u.sym->temporary)
369 		      	addlocal(tp->u.sym);
370 		      p = node(tp->op + sizeop(voidptype->size), NULL, NULL, tp->u.sym); } break;
371 	default:assert(0);
372 	}
373 	tp->node = p;
374 	return p;
375 }
list(Node p)376 static void list(Node p) {
377 	if (p && p->link == NULL) {
378 		if (forest) {
379 			p->link = forest->link;
380 			forest->link = p;
381 		} else
382 			p->link = p;
383 		forest = p;
384 	}
385 }
labelnode(int lab)386 static void labelnode(int lab) {
387 	assert(lab);
388 	if (forest && forest->op == LABEL+V)
389 		equatelab(findlabel(lab), forest->syms[0]);
390 	else
391 		list(newnode(LABEL+V, NULL, NULL, findlabel(lab)));
392 	reset();
393 }
unlist(void)394 static void unlist(void) {
395 	Node p;
396 
397 	assert(forest);
398 	assert(forest != forest->link);
399 	p = forest->link;
400 	while (p->link != forest)
401 		p = p->link;
402 	p->link = forest->link;
403 	forest = p;
404 }
cvtconst(Tree p)405 Tree cvtconst(Tree p) {
406 	Symbol q = constant(p->type, p->u.v);
407 	Tree e;
408 
409 	if (q->u.c.loc == NULL)
410 		q->u.c.loc = genident(STATIC, p->type, GLOBAL);
411 	if (isarray(p->type)) {
412 		e = simplify(ADDRG, atop(p->type), NULL, NULL);
413 		e->u.sym = q->u.c.loc;
414 	} else
415 		e = idtree(q->u.c.loc);
416 	return e;
417 }
gencode(Symbol caller[],Symbol callee[])418 void gencode(Symbol caller[], Symbol callee[]) {
419 	Code cp;
420 	Coordinate save;
421 
422 	if (prunetemps == -1)
423 		prunetemps = !IR->wants_dag;
424 	save = src;
425 	if (assignargs) {
426 		int i;
427 		Symbol p, q;
428 		cp = codehead.next->next;
429 		codelist = codehead.next;
430 		for (i = 0; (p = callee[i]) != NULL
431 		         && (q = caller[i]) != NULL; i++)
432 			if (p->sclass != q->sclass || p->type != q->type)
433 				walk(asgn(p, idtree(q)), 0, 0);
434 		codelist->next = cp;
435 		cp->prev = codelist;
436 	}
437 	if (glevel && IR->stabsym) {
438 		int i;
439 		Symbol p, q;
440 		for (i = 0; (p = callee[i]) != NULL
441 		         && (q = caller[i]) != NULL; i++) {
442 			(*IR->stabsym)(p);
443 			if (p->sclass != q->sclass || p->type != q->type)
444 				(*IR->stabsym)(q);
445 		}
446 		swtoseg(CODE);
447 	}
448 	cp = codehead.next;
449 	for ( ; errcnt <= 0 && cp; cp = cp->next)
450 		switch (cp->kind) {
451 		case Address:  (*IR->address)(cp->u.addr.sym, cp->u.addr.base,
452 			       	cp->u.addr.offset); break;
453 		case Blockbeg: {
454 			       	Symbol *p = cp->u.block.locals;
455 			       	(*IR->blockbeg)(&cp->u.block.x);
456 			       	for ( ; *p; p++)
457 			       		if ((*p)->ref != 0.0)
458 			       			(*IR->local)(*p);
459 			       		else if (glevel) (*IR->local)(*p);
460 			       }
461  break;
462 		case Blockend: (*IR->blockend)(&cp->u.begin->u.block.x); break;
463 		case Defpoint: src = cp->u.point.src; break;
464 		case Gen: case Jump:
465 		case Label:    if (prunetemps)
466 			       	cp->u.forest = prune(cp->u.forest);
467 			       fixup(cp->u.forest);
468 			       cp->u.forest = (*IR->gen)(cp->u.forest); break;
469 		case Local:    (*IR->local)(cp->u.var); break;
470 		case Switch:   break;
471 		default: assert(0);
472 		}
473 	src = save;
474 }
fixup(Node p)475 static void fixup(Node p) {
476 	for ( ; p; p = p->link)
477 		switch (generic(p->op)) {
478 		case JUMP:
479 			if (specific(p->kids[0]->op) == ADDRG+P)
480 				p->kids[0]->syms[0] =
481 					equated(p->kids[0]->syms[0]);
482 			break;
483 		case LABEL: assert(p->syms[0] == equated(p->syms[0])); break;
484 		case EQ: case GE: case GT: case LE: case LT: case NE:
485 			assert(p->syms[0]);
486 			p->syms[0] = equated(p->syms[0]);
487 		}
488 }
equated(Symbol p)489 static Symbol equated(Symbol p) {
490 	{ Symbol q; for (q = p->u.l.equatedto; q; q = q->u.l.equatedto) assert(p != q); }
491 	while (p->u.l.equatedto)
492 		p = p->u.l.equatedto;
493 	return p;
494 }
emitcode(void)495 void emitcode(void) {
496 	Code cp;
497 	Coordinate save;
498 
499 	save = src;
500 	cp = codehead.next;
501 	for ( ; errcnt <= 0 && cp; cp = cp->next)
502 		switch (cp->kind) {
503 		case Address: break;
504 		case Blockbeg: if (glevel && IR->stabblock) {
505 			       	(*IR->stabblock)('{',  cp->u.block.level - LOCAL, cp->u.block.locals);
506 			       	swtoseg(CODE);
507 			       }
508  break;
509 		case Blockend: if (glevel && IR->stabblock) {
510 			       	Code bp = cp->u.begin;
511 			       	foreach(bp->u.block.identifiers, bp->u.block.level, typestab, NULL);
512 			       	foreach(bp->u.block.types,       bp->u.block.level, typestab, NULL);
513 			       	(*IR->stabblock)('}', bp->u.block.level - LOCAL, bp->u.block.locals);
514 			       	swtoseg(CODE);
515 			       }
516  break;
517 		case Defpoint: src = cp->u.point.src;
518 			       if (glevel > 0 && IR->stabline) {
519 			       	(*IR->stabline)(&cp->u.point.src); swtoseg(CODE); } break;
520 		case Gen: case Jump:
521 		case Label:    if (cp->u.forest)
522 			       	(*IR->emit)(cp->u.forest); break;
523 		case Local:    if (glevel && IR->stabsym) {
524 			       	(*IR->stabsym)(cp->u.var);
525 			       	swtoseg(CODE);
526 			       } break;
527 		case Switch:   {	int i;
528 			       	defglobal(cp->u.swtch.table, LIT);
529 			       	(*IR->defaddress)(equated(cp->u.swtch.labels[0]));
530 			       	for (i = 1; i < cp->u.swtch.size; i++) {
531 			       		long k = cp->u.swtch.values[i-1];
532 			       		while (++k < cp->u.swtch.values[i])
533 			       			assert(k < LONG_MAX),
534 			       			(*IR->defaddress)(equated(cp->u.swtch.deflab));
535 			       		(*IR->defaddress)(equated(cp->u.swtch.labels[i]));
536 			       	}
537 			       	swtoseg(CODE);
538 			       } break;
539 		default: assert(0);
540 		}
541 	src = save;
542 }
543 
undag(Node forest)544 static Node undag(Node forest) {
545 	Node p;
546 
547 	tail = &forest;
548 	for (p = forest; p; p = p->link)
549 		if (generic(p->op) == INDIR) {
550 			assert(p->count >= 1);
551 			visit(p, 1);
552 			if (p->syms[2]) {
553 				assert(p->syms[2]->u.t.cse);
554 				p->syms[2]->u.t.cse = NULL;
555 				addlocal(p->syms[2]);
556 			}
557 		} else if (iscall(p->op) && p->count >= 1)
558 			visit(p, 1);
559 		else {
560 			assert(p->count == 0),
561 			visit(p, 1);
562 			*tail = p;
563 			tail = &p->link;
564 		}
565 	*tail = NULL;
566 	return forest;
567 }
replace(Node p)568 static Node replace(Node p) {
569 	if (p && (  generic(p->op) == INDIR
570 		 && generic(p->kids[0]->op) == ADDRL
571 		 && p->kids[0]->syms[0]->temporary
572 		 && p->kids[0]->syms[0]->u.t.replace)) {
573 		p = p->kids[0]->syms[0]->u.t.cse;
574 		if (generic(p->op) == INDIR && isaddrop(p->kids[0]->op))
575 			p = newnode(p->op, newnode(p->kids[0]->op, NULL, NULL,
576 				p->kids[0]->syms[0]), NULL, NULL);
577 		else if (generic(p->op) == ADDRG)
578 			p = newnode(p->op, NULL, NULL, p->syms[0]);
579 		else
580 			assert(0);
581 		p->count = 1;
582 	} else if (p) {
583 		p->kids[0] = replace(p->kids[0]);
584 		p->kids[1] = replace(p->kids[1]);
585 	}
586 	return p;
587 }
prune(Node forest)588 static Node prune(Node forest) {
589 	Node p, *tail = &forest;
590 	int count = 0;
591 
592 	for (p = forest; p; p = p->link) {
593 		if (count > 0) {
594 			p->kids[0] = replace(p->kids[0]);
595 			p->kids[1] = replace(p->kids[1]);
596 		}
597 		if ((  generic(p->op) == ASGN
598 		    && generic(p->kids[0]->op) == ADDRL
599 		    && p->kids[0]->syms[0]->temporary
600 		    && p->kids[0]->syms[0]->u.t.cse == p->kids[1])) {
601 			Symbol tmp = p->kids[0]->syms[0];
602 			if (!tmp->defined)
603 				(*IR->local)(tmp);
604 			tmp->defined = 1;
605 			if ((  generic(p->kids[1]->op) == INDIR
606 			    && isaddrop(p->kids[1]->kids[0]->op)
607 			    && p->kids[1]->kids[0]->syms[0]->sclass == REGISTER)
608 			|| ((  generic(p->kids[1]->op) == INDIR
609 			    && isaddrop(p->kids[1]->kids[0]->op)) && tmp->sclass == AUTO)
610 			|| (generic(p->kids[1]->op) == ADDRG && tmp->sclass == AUTO)) {
611 				tmp->u.t.replace = 1;
612 				count++;
613 				continue;	/* and omit the assignment */
614 			}
615 		}
616 		/* keep the assignment and other roots */
617 		*tail = p;
618 		tail = &(*tail)->link;
619 	}
620 	assert(*tail == NULL);
621 	return forest;
622 }
visit(Node p,int listed)623 static Node visit(Node p, int listed) {
624 	if (p) {
625 		if (p->syms[2])
626 			p = tmpnode(p);
627 		else if ((p->count <= 1 && !iscall(p->op))
628 		||       (p->count == 0 &&  iscall(p->op))) {
629 			p->kids[0] = visit(p->kids[0], 0);
630 			p->kids[1] = visit(p->kids[1], 0);
631 		}
632 
633 		else if (specific(p->op) == ADDRL+P || specific(p->op) == ADDRF+P) {
634 			assert(!listed);
635 			p = newnode(p->op, NULL, NULL, p->syms[0]);
636 			p->count = 1;
637 		}
638 		else if (p->op == INDIR+B) {
639 			p = newnode(p->op, p->kids[0], NULL, NULL);
640 			p->count = 1;
641 			p->kids[0] = visit(p->kids[0], 0);
642 			p->kids[1] = visit(p->kids[1], 0);
643 		}
644 		else {
645 			p->kids[0] = visit(p->kids[0], 0);
646 			p->kids[1] = visit(p->kids[1], 0);
647 			p->syms[2] = temporary(REGISTER, btot(p->op, opsize(p->op)));
648 			assert(!p->syms[2]->defined);
649 			p->syms[2]->ref = 1;
650 			p->syms[2]->u.t.cse = p;
651 
652 			*tail = asgnnode(p->syms[2], p);
653 			tail = &(*tail)->link;
654 			if (!listed)
655 				p = tmpnode(p);
656 		};
657 	}
658 	return p;
659 }
tmpnode(Node p)660 static Node tmpnode(Node p) {
661 	Symbol tmp = p->syms[2];
662 
663 	assert(tmp);
664 	if (--p->count == 0)
665 		p->syms[2] = NULL;
666 	p = newnode(INDIR + ttob(tmp->type),
667 		newnode(ADDRL + ttob(voidptype), NULL, NULL, tmp), NULL, NULL);
668 	p->count = 1;
669 	return p;
670 }
asgnnode(Symbol tmp,Node p)671 static Node asgnnode(Symbol tmp, Node p) {
672 	p = newnode(ASGN + ttob(tmp->type),
673 		newnode(ADDRL + ttob(voidptype), NULL, NULL, tmp), p, NULL);
674 	p->syms[0] = intconst(tmp->type->size);
675 	p->syms[1] = intconst(tmp->type->align);
676 	return p;
677 }
678 /* printdag - print dag p on fd, or the node list if p == 0 */
printdag(Node p,int fd)679 void printdag(Node p, int fd) {
680 	FILE *f = fd == 1 ? stdout : stderr;
681 
682 	printed(0);
683 	if (p == 0) {
684 		if ((p = forest) != NULL)
685 			do {
686 				p = p->link;
687 				printdag1(p, fd, 0);
688 			} while (p != forest);
689 	} else if (*printed(nodeid((Tree)p)))
690 		fprint(f, "node'%d printed above\n", nodeid((Tree)p));
691 	else
692 		printdag1(p, fd, 0);
693 }
694 
695 /* printdag1 - recursively print dag p */
printdag1(Node p,int fd,int lev)696 static void printdag1(Node p, int fd, int lev) {
697 	int id, i;
698 
699 	if (p == 0 || *printed(id = nodeid((Tree)p)))
700 		return;
701 	*printed(id) = 1;
702 	for (i = 0; i < NELEMS(p->kids); i++)
703 		printdag1(p->kids[i], fd, lev + 1);
704 	printnode(p, fd, lev);
705 }
706 
707 /* printnode - print fields of dag p */
printnode(Node p,int fd,int lev)708 static void printnode(Node p, int fd, int lev) {
709 	if (p) {
710 		FILE *f = fd == 1 ? stdout : stderr;
711 		int i, id = nodeid((Tree)p);
712 		fprint(f, "%c%d%s", lev == 0 ? '\'' : '#', id,
713 			&"   "[id < 10 ? 0 : id < 100 ? 1 : 2]);
714 		fprint(f, "%s count=%d", opname(p->op), p->count);
715 		for (i = 0; i < NELEMS(p->kids) && p->kids[i]; i++)
716 			fprint(f, " #%d", nodeid((Tree)p->kids[i]));
717 		if (generic(p->op) == CALL && p->syms[0] && p->syms[0]->type)
718 			fprint(f, " {%t}", p->syms[0]->type);
719 		else
720 			for (i = 0; i < NELEMS(p->syms) && p->syms[i]; i++)
721 				if (p->syms[i]->name)
722 					fprint(f, " %s", p->syms[i]->name);
723 				else
724 					fprint(f, " %p", p->syms[i]);
725 		fprint(f, "\n");
726 	}
727 }
728 
729 /* typestab - emit stab entries for p */
typestab(Symbol p,void * cl)730 static void typestab(Symbol p, void *cl) {
731 	if (!isfunc(p->type) && (p->sclass == EXTERN || p->sclass == STATIC) && IR->stabsym)
732 		(*IR->stabsym)(p);
733 	else if ((p->sclass == TYPEDEF || p->sclass == 0) && IR->stabtype)
734 		(*IR->stabtype)(p);
735 }
736 
737