1 #include "c.h"
2 
3 
4 int where = STMT;
5 static int warn;
6 static int nid = 1;		/* identifies trees & nodes in debugging output */
7 static struct nodeid {
8 	int printed;
9 	Tree node;
10 } ids[500];			/* if ids[i].node == p, then p's id is i */
11 
12 static void printtree1(Tree, int, int);
13 
tree(int op,Type type,Tree left,Tree right)14 Tree tree(int op, Type type, Tree left, Tree right) {
15 	Tree p;
16 
17 	NEW0(p, where);
18 	p->op = op;
19 	p->type = type;
20 	p->kids[0] = left;
21 	p->kids[1] = right;
22 	return p;
23 }
24 
texpr(Tree (* f)(int),int tok,int a)25 Tree texpr(Tree (*f)(int), int tok, int a) {
26 	int save = where;
27 	Tree p;
28 
29 	where = a;
30 	p = (*f)(tok);
31 	where = save;
32 	return p;
33 }
root1(Tree p)34 static Tree root1(Tree p) {
35 	if (p == NULL)
36 		return p;
37 	if (p->type == voidtype)
38 		warn++;
39 	switch (generic(p->op)) {
40 	case COND: {
41 		Tree q = p->kids[1];
42 		assert(q && q->op == RIGHT);
43 		if (p->u.sym && q->kids[0] && generic(q->kids[0]->op) == ASGN)
44 			q->kids[0] = root1(q->kids[0]->kids[1]);
45 		else
46 			q->kids[0] = root1(q->kids[0]);
47 		if (p->u.sym && q->kids[1] && generic(q->kids[1]->op) == ASGN)
48 			q->kids[1] = root1(q->kids[1]->kids[1]);
49 		else
50 			q->kids[1] = root1(q->kids[1]);
51 		p->u.sym = 0;
52 		if (q->kids[0] == 0 && q->kids[1] == 0)
53 			p = root1(p->kids[0]);
54 		}
55 		break;
56 	case AND: case OR:
57 		if ((p->kids[1] = root1(p->kids[1])) == 0)
58 			p = root1(p->kids[0]);
59 		break;
60 	case NOT:
61 		if (warn++ == 0)
62 			warning("expression with no effect elided\n");
63 		return root1(p->kids[0]);
64 	case RIGHT:
65 		if (p->kids[1] == 0)
66 			return root1(p->kids[0]);
67 		if (p->kids[0] && p->kids[0]->op == CALL+B
68 		&&  p->kids[1] && p->kids[1]->op == INDIR+B)
69 			/* avoid premature release of the CALL+B temporary */
70 			return p->kids[0];
71 		if (p->kids[0] && p->kids[0]->op == RIGHT
72 		&&  p->kids[1] == p->kids[0]->kids[0])
73 			/* de-construct e++ construction */
74 			return p->kids[0]->kids[1];
75 		p = tree(RIGHT, p->type, root1(p->kids[0]), root1(p->kids[1]));
76 		return p->kids[0] || p->kids[1] ? p : (Tree)0;
77 	case EQ:  case NE:  case GT:   case GE:  case LE:  case LT:
78 	case ADD: case SUB: case MUL:  case DIV: case MOD:
79 	case LSH: case RSH: case BAND: case BOR: case BXOR:
80 		if (warn++ == 0)
81 			warning("expression with no effect elided\n");
82 		p = tree(RIGHT, p->type, root1(p->kids[0]), root1(p->kids[1]));
83 		return p->kids[0] || p->kids[1] ? p : (Tree)0;
84 	case INDIR:
85 		if (p->type->size == 0 && unqual(p->type) != voidtype)
86 			warning("reference to `%t' elided\n", p->type);
87 		if (isptr(p->kids[0]->type) && isvolatile(p->kids[0]->type->type))
88 			warning("reference to `volatile %t' elided\n", p->type);
89 		/* fall thru */
90 	case CVI: case CVF: case CVU: case CVP:
91 	case NEG: case BCOM: case FIELD:
92 		if (warn++ == 0)
93 			warning("expression with no effect elided\n");
94 		return root1(p->kids[0]);
95 	case ADDRL: case ADDRG: case ADDRF: case CNST:
96 		if (needconst)
97 			return p;
98 		if (warn++ == 0)
99 			warning("expression with no effect elided\n");
100 		return NULL;
101 	case ARG: case ASGN: case CALL: case JUMP: case LABEL:
102 		break;
103 	default: assert(0);
104 	}
105 	return p;
106 }
107 
root(Tree p)108 Tree root(Tree p) {
109 	warn = 0;
110 	return root1(p);
111 }
112 
opname(int op)113 char *opname(int op) {
114 	static char *opnames[] = {
115 	"",
116 	"CNST",
117 	"ARG",
118 	"ASGN",
119 	"INDIR",
120 	"CVC",
121 	"CVD",
122 	"CVF",
123 	"CVI",
124 	"CVP",
125 	"CVS",
126 	"CVU",
127 	"NEG",
128 	"CALL",
129 	"*LOAD*",
130 	"RET",
131 	"ADDRG",
132 	"ADDRF",
133 	"ADDRL",
134 	"ADD",
135 	"SUB",
136 	"LSH",
137 	"MOD",
138 	"RSH",
139 	"BAND",
140 	"BCOM",
141 	"BOR",
142 	"BXOR",
143 	"DIV",
144 	"MUL",
145 	"EQ",
146 	"GE",
147 	"GT",
148 	"LE",
149 	"LT",
150 	"NE",
151 	"JUMP",
152 	"LABEL",
153 	"AND",
154 	"NOT",
155 	"OR",
156 	"COND",
157 	"RIGHT",
158 	"FIELD"
159 	}, *suffixes[] = {
160 		"0", "F", "D", "C", "S", "I", "U", "P", "V", "B",
161 		"10","11","12","13","14","15"
162 	};
163 
164 	if (generic(op) >= AND && generic(op) <= FIELD && opsize(op) == 0)
165 		return opnames[opindex(op)];
166 	return stringf("%s%s%s",
167 		opindex(op) > 0 && opindex(op) < NELEMS(opnames) ?
168 			opnames[opindex(op)] : stringd(opindex(op)),
169 		suffixes[optype(op)], opsize(op) > 0 ? stringd(opsize(op)) : "");
170 }
171 
nodeid(Tree p)172 int nodeid(Tree p) {
173 	int i = 1;
174 
175 	ids[nid].node = p;
176 	while (ids[i].node != p)
177 		i++;
178 	if (i == nid)
179 		ids[nid++].printed = 0;
180 	return i;
181 }
182 
183 /* printed - return pointer to ids[id].printed */
printed(int id)184 int *printed(int id) {
185 	if (id)
186 		return &ids[id].printed;
187 	nid = 1;
188 	return 0;
189 }
190 
191 /* printtree - print tree p on fd */
printtree(Tree p,int fd)192 void printtree(Tree p, int fd) {
193 	(void)printed(0);
194 	printtree1(p, fd, 1);
195 }
196 
197 /* printtree1 - recursively print tree p */
printtree1(Tree p,int fd,int lev)198 static void printtree1(Tree p, int fd, int lev) {
199 	FILE *f = fd == 1 ? stdout : stderr;
200 	int i;
201 	static char blanks[] = "                                                   ";
202 
203 	if (p == 0 || *printed(i = nodeid(p)))
204 		return;
205 	fprint(f, "#%d%S%S", i, blanks, i < 10 ? 2 : i < 100 ? 1 : 0, blanks, lev);
206 	fprint(f, "%s %t", opname(p->op), p->type);
207 	*printed(i) = 1;
208 	for (i = 0; i < NELEMS(p->kids); i++)
209 		if (p->kids[i])
210 			fprint(f, " #%d", nodeid(p->kids[i]));
211 	if (p->op == FIELD && p->u.field)
212 		fprint(f, " %s %d..%d", p->u.field->name,
213 			fieldsize(p->u.field) + fieldright(p->u.field), fieldright(p->u.field));
214 	else if (generic(p->op) == CNST)
215 		fprint(f, " %s", vtoa(p->type, p->u.v));
216 	else if (p->u.sym)
217 		fprint(f, " %s", p->u.sym->name);
218 	if (p->node)
219 		fprint(f, " node=%p", p->node);
220 	fprint(f, "\n");
221 	for (i = 0; i < NELEMS(p->kids); i++)
222 		printtree1(p->kids[i], fd, lev + 1);
223 }
224