* added compilers lcc and bcc (linux86)
[mascara-docs.git] / compilers / lcc-4.2 / src / simp.c
blobf95591fb99543716851470670acefaeeb8812204
1 #include "c.h"
2 #include <float.h>
4 static char rcsid[] = "$Id$";
6 #define foldcnst(TYPE,VAR,OP) \
7 if (l->op == CNST+TYPE && r->op == CNST+TYPE) \
8 return cnsttree(ty, l->u.v.VAR OP r->u.v.VAR)
9 #define commute(L,R) \
10 if (generic(R->op) == CNST && generic(L->op) != CNST) \
11 do { Tree t = L; L = R; R = t; } while(0)
12 #define xfoldcnst(TYPE,VAR,OP,FUNC)\
13 if (l->op == CNST+TYPE && r->op == CNST+TYPE\
14 && FUNC(l->u.v.VAR,r->u.v.VAR,\
15 ty->u.sym->u.limits.min.VAR,\
16 ty->u.sym->u.limits.max.VAR, needconst)) \
17 return cnsttree(ty, l->u.v.VAR OP r->u.v.VAR)
18 #define xcvtcnst(FTYPE,SRC,DST,VAR,EXPR) \
19 if (l->op == CNST+FTYPE) do {\
20 if (!explicitCast\
21 && ((SRC) < DST->u.sym->u.limits.min.VAR || (SRC) > DST->u.sym->u.limits.max.VAR))\
22 warning("overflow in converting constant expression from `%t' to `%t'\n", l->type, DST);\
23 if (needconst\
24 || !((SRC) < DST->u.sym->u.limits.min.VAR || (SRC) > DST->u.sym->u.limits.max.VAR))\
25 return cnsttree(ty, (EXPR)); } while(0)
26 #define identity(X,Y,TYPE,VAR,VAL) \
27 if (X->op == CNST+TYPE && X->u.v.VAR == VAL) return Y
28 #define zerofield(OP,TYPE,VAR) \
29 if (l->op == FIELD \
30 && r->op == CNST+TYPE && r->u.v.VAR == 0)\
31 return eqtree(OP, bittree(BAND, l->kids[0],\
32 cnsttree(unsignedtype, \
33 (unsigned long)fieldmask(l->u.field)<<fieldright(l->u.field))), r)
34 #define cfoldcnst(TYPE,VAR,OP) \
35 if (l->op == CNST+TYPE && r->op == CNST+TYPE) \
36 return cnsttree(inttype, (long)(l->u.v.VAR OP r->u.v.VAR))
37 #define foldaddp(L,R,RTYPE,VAR) \
38 if (L->op == CNST+P && R->op == CNST+RTYPE) { \
39 Tree e = tree(CNST+P, ty, NULL, NULL);\
40 e->u.v.p = (char *)L->u.v.p + R->u.v.VAR;\
41 return e; }
42 #define ufoldcnst(TYPE,EXP) if (l->op == CNST+TYPE) return EXP
43 #define sfoldcnst(OP) \
44 if (l->op == CNST+U && r->op == CNST+I \
45 && r->u.v.i >= 0 && r->u.v.i < 8*l->type->size) \
46 return cnsttree(ty, (unsigned long)(l->u.v.u OP r->u.v.i))
47 #define geu(L,R,V) \
48 if (R->op == CNST+U && R->u.v.u == 0) do { \
49 warning("result of unsigned comparison is constant\n"); \
50 return tree(RIGHT, inttype, root(L), cnsttree(inttype, (long)(V))); } while(0)
51 #define idempotent(OP) if (l->op == OP) return l->kids[0]
53 int needconst;
54 int explicitCast;
55 static int addi(long x, long y, long min, long max, int needconst) {
56 int cond = x == 0 || y == 0
57 || x < 0 && y < 0 && x >= min - y
58 || x < 0 && y > 0
59 || x > 0 && y < 0
60 || x > 0 && y > 0 && x <= max - y;
61 if (!cond && needconst) {
62 warning("overflow in constant expression\n");
63 cond = 1;
65 return cond;
70 static int addd(double x, double y, double min, double max, int needconst) {
71 int cond = x == 0 || y == 0
72 || x < 0 && y < 0 && x >= min - y
73 || x < 0 && y > 0
74 || x > 0 && y < 0
75 || x > 0 && y > 0 && x <= max - y;
76 if (!cond && needconst) {
77 warning("overflow in constant expression\n");
78 cond = 1;
80 return cond;
85 static Tree addrtree(Tree e, long n, Type ty) {
86 Symbol p = e->u.sym, q;
88 if (p->scope == GLOBAL
89 || p->sclass == STATIC || p->sclass == EXTERN)
90 NEW0(q, PERM);
91 else
92 NEW0(q, FUNC);
93 q->name = stringd(genlabel(1));
94 q->sclass = p->sclass;
95 q->scope = p->scope;
96 assert(isptr(ty) || isarray(ty));
97 q->type = isptr(ty) ? ty->type : ty;
98 q->temporary = p->temporary;
99 q->generated = p->generated;
100 q->addressed = p->addressed;
101 q->computed = 1;
102 q->defined = 1;
103 q->ref = 1;
104 assert(IR->address);
105 if (p->scope == GLOBAL
106 || p->sclass == STATIC || p->sclass == EXTERN) {
107 if (p->sclass == AUTO)
108 q->sclass = STATIC;
109 (*IR->address)(q, p, n);
110 } else {
111 Code cp;
112 addlocal(p);
113 cp = code(Address);
114 cp->u.addr.sym = q;
115 cp->u.addr.base = p;
116 cp->u.addr.offset = n;
118 e = tree(e->op, ty, NULL, NULL);
119 e->u.sym = q;
120 return e;
123 /* div[id] - return 1 if min <= x/y <= max, 0 otherwise */
124 static int divi(long x, long y, long min, long max, int needconst) {
125 int cond = y != 0 && !(x == min && y == -1);
126 if (!cond && needconst) {
127 warning("overflow in constant expression\n");
128 cond = 1;
130 return cond;
135 static int divd(double x, double y, double min, double max, int needconst) {
136 int cond;
138 if (x < 0) x = -x;
139 if (y < 0) y = -y;
140 cond = y != 0 && !(y < 1 && x > max*y);
141 if (!cond && needconst) {
142 warning("overflow in constant expression\n");
143 cond = 1;
145 return cond;
149 /* mul[id] - return 1 if min <= x*y <= max, 0 otherwise */
150 static int muli(long x, long y, long min, long max, int needconst) {
151 int cond = x > -1 && x <= 1 || y > -1 && y <= 1
152 || x < 0 && y < 0 && -x <= max/-y
153 || x < 0 && y > 0 && x >= min/y
154 || x > 0 && y < 0 && y >= min/x
155 || x > 0 && y > 0 && x <= max/y;
156 if (!cond && needconst) {
157 warning("overflow in constant expression\n");
158 cond = 1;
160 return cond;
165 static int muld(double x, double y, double min, double max, int needconst) {
166 int cond = x >= -1 && x <= 1 || y >= -1 && y <= 1
167 || x < 0 && y < 0 && -x <= max/-y
168 || x < 0 && y > 0 && x >= min/y
169 || x > 0 && y < 0 && y >= min/x
170 || x > 0 && y > 0 && x <= max/y;
171 if (!cond && needconst) {
172 warning("overflow in constant expression\n");
173 cond = 1;
175 return cond;
179 /* sub[id] - return 1 if min <= x-y <= max, 0 otherwise */
180 static int subi(long x, long y, long min, long max, int needconst) {
181 return addi(x, -y, min, max, needconst);
184 static int subd(double x, double y, double min, double max, int needconst) {
185 return addd(x, -y, min, max, needconst);
187 Tree constexpr(int tok) {
188 Tree p;
190 needconst++;
191 p = expr1(tok);
192 needconst--;
193 return p;
196 int intexpr(int tok, int n) {
197 Tree p = constexpr(tok);
199 needconst++;
200 if (p->op == CNST+I || p->op == CNST+U)
201 n = cast(p, inttype)->u.v.i;
202 else
203 error("integer expression must be constant\n");
204 needconst--;
205 return n;
207 Tree simplify(int op, Type ty, Tree l, Tree r) {
208 int n;
209 Tree p;
211 if (optype(op) == 0)
212 op = mkop(op, ty);
213 switch (op) {
214 case ADD+U:
215 foldcnst(U,u,+);
216 commute(r,l);
217 identity(r,l,U,u,0);
218 break;
219 case ADD+I:
220 xfoldcnst(I,i,+,addi);
221 commute(r,l);
222 identity(r,l,I,i,0);
223 break;
224 case CVI+I:
225 xcvtcnst(I,l->u.v.i,ty,i,(long)extend(l->u.v.i,ty));
226 break;
227 case CVU+I:
228 if (l->op == CNST+U) {
229 if (!explicitCast && l->u.v.u > ty->u.sym->u.limits.max.i)
230 warning("overflow in converting constant expression from `%t' to `%t'\n", l->type, ty);
231 if (needconst || !(l->u.v.u > ty->u.sym->u.limits.max.i))
232 return cnsttree(ty, (long)extend(l->u.v.u,ty));
234 break;
235 case CVP+U:
236 xcvtcnst(P,(unsigned long)l->u.v.p,ty,u,(unsigned long)l->u.v.p);
237 break;
238 case CVU+P:
239 xcvtcnst(U,(void*)l->u.v.u,ty,p,(void*)l->u.v.u);
240 break;
241 case CVP+P:
242 xcvtcnst(P,l->u.v.p,ty,p,l->u.v.p);
243 break;
244 case CVI+U:
245 xcvtcnst(I,l->u.v.i,ty,u,((unsigned long)l->u.v.i)&ones(8*ty->size));
246 break;
247 case CVU+U:
248 xcvtcnst(U,l->u.v.u,ty,u,l->u.v.u&ones(8*ty->size));
249 break;
251 case CVI+F:
252 xcvtcnst(I,l->u.v.i,ty,d,(long double)l->u.v.i);
253 case CVU+F:
254 xcvtcnst(U,l->u.v.u,ty,d,(long double)l->u.v.u);
255 break;
256 case CVF+I:
257 xcvtcnst(F,l->u.v.d,ty,i,(long)l->u.v.d);
258 break;
259 case CVF+F: {
260 float d;
261 if (l->op == CNST+F)
262 if (l->u.v.d < ty->u.sym->u.limits.min.d)
263 d = ty->u.sym->u.limits.min.d;
264 else if (l->u.v.d > ty->u.sym->u.limits.max.d)
265 d = ty->u.sym->u.limits.max.d;
266 else
267 d = l->u.v.d;
268 xcvtcnst(F,l->u.v.d,ty,d,(long double)d);
269 break;
271 case BAND+U:
272 foldcnst(U,u,&);
273 commute(r,l);
274 identity(r,l,U,u,ones(8*ty->size));
275 if (r->op == CNST+U && r->u.v.u == 0)
276 return tree(RIGHT, ty, root(l), cnsttree(ty, 0UL));
277 break;
278 case BAND+I:
279 foldcnst(I,i,&);
280 commute(r,l);
281 identity(r,l,I,i,ones(8*ty->size));
282 if (r->op == CNST+I && r->u.v.u == 0)
283 return tree(RIGHT, ty, root(l), cnsttree(ty, 0L));
284 break;
286 case MUL+U:
287 commute(l,r);
288 if (l->op == CNST+U && (n = ispow2(l->u.v.u)) != 0)
289 return simplify(LSH, ty, r, cnsttree(inttype, (long)n));
290 foldcnst(U,u,*);
291 identity(r,l,U,u,1);
292 break;
293 case NE+I:
294 cfoldcnst(I,i,!=);
295 commute(r,l);
296 zerofield(NE,I,i);
297 break;
299 case EQ+I:
300 cfoldcnst(I,i,==);
301 commute(r,l);
302 zerofield(EQ,I,i);
303 break;
304 case ADD+P:
305 foldaddp(l,r,I,i);
306 foldaddp(l,r,U,u);
307 foldaddp(r,l,I,i);
308 foldaddp(r,l,U,u);
309 commute(r,l);
310 identity(r,retype(l,ty),I,i,0);
311 identity(r,retype(l,ty),U,u,0);
313 Some assemblers, e.g., the MIPS, can't handle offsets
314 larger than 16 bits. A better solution would be to change
315 the interface so that address() could fail.
317 if (l->op == ADDRG+P && l->u.sym->generated
318 && (r->op == CNST+I && (r->u.v.i > 32767 || r->u.v.i < -32768)
319 || r->op == CNST+U && r->u.v.u > 65536))
320 break;
321 if (IR->address
322 && isaddrop(l->op)
323 && (r->op == CNST+I && r->u.v.i <= longtype->u.sym->u.limits.max.i
324 && r->u.v.i >= longtype->u.sym->u.limits.min.i
325 || r->op == CNST+U && r->u.v.u <= longtype->u.sym->u.limits.max.i))
326 return addrtree(l, cast(r, longtype)->u.v.i, ty);
327 if (IR->address
328 && l->op == ADD+P && isaddrop(l->kids[1]->op)
329 && (r->op == CNST+I && r->u.v.i <= longtype->u.sym->u.limits.max.i
330 && r->u.v.i >= longtype->u.sym->u.limits.min.i
331 || r->op == CNST+U && r->u.v.u <= longtype->u.sym->u.limits.max.i))
332 return simplify(ADD+P, ty, l->kids[0],
333 addrtree(l->kids[1], cast(r, longtype)->u.v.i, ty));
334 if ((l->op == ADD+I || l->op == SUB+I)
335 && l->kids[1]->op == CNST+I && isaddrop(r->op))
336 return simplify(ADD+P, ty, l->kids[0],
337 simplify(generic(l->op)+P, ty, r, l->kids[1]));
338 if (l->op == ADD+P && generic(l->kids[1]->op) == CNST
339 && generic(r->op) == CNST)
340 return simplify(ADD+P, ty, l->kids[0],
341 simplify(ADD, l->kids[1]->type, l->kids[1], r));
342 if (l->op == ADD+I && generic(l->kids[1]->op) == CNST
343 && r->op == ADD+P && generic(r->kids[1]->op) == CNST)
344 return simplify(ADD+P, ty, l->kids[0],
345 simplify(ADD+P, ty, r->kids[0],
346 simplify(ADD, r->kids[1]->type, l->kids[1], r->kids[1])));
347 if (l->op == RIGHT && l->kids[1])
348 return tree(RIGHT, ty, l->kids[0],
349 simplify(ADD+P, ty, l->kids[1], r));
350 else if (l->op == RIGHT && l->kids[0])
351 return tree(RIGHT, ty,
352 simplify(ADD+P, ty, l->kids[0], r), NULL);
353 break;
355 case ADD+F:
356 xfoldcnst(F,d,+,addd);
357 commute(r,l);
358 break;
359 case AND+I:
360 op = AND;
361 ufoldcnst(I,l->u.v.i ? cond(r) : l); /* 0&&r => 0, 1&&r => r */
362 break;
363 case OR+I:
364 op = OR;
365 /* 0||r => r, 1||r => 1 */
366 ufoldcnst(I,l->u.v.i ? cnsttree(ty, 1L) : cond(r));
367 break;
368 case BCOM+I:
369 ufoldcnst(I,cnsttree(ty, (long)extend((~l->u.v.i)&ones(8*ty->size), ty)));
370 idempotent(BCOM+U);
371 break;
372 case BCOM+U:
373 ufoldcnst(U,cnsttree(ty, (unsigned long)((~l->u.v.u)&ones(8*ty->size))));
374 idempotent(BCOM+U);
375 break;
376 case BOR+U:
377 foldcnst(U,u,|);
378 commute(r,l);
379 identity(r,l,U,u,0);
380 break;
381 case BOR+I:
382 foldcnst(I,i,|);
383 commute(r,l);
384 identity(r,l,I,i,0);
385 break;
386 case BXOR+U:
387 foldcnst(U,u,^);
388 commute(r,l);
389 identity(r,l,U,u,0);
390 break;
391 case BXOR+I:
392 foldcnst(I,i,^);
393 commute(r,l);
394 identity(r,l,I,i,0);
395 break;
396 case DIV+F:
397 xfoldcnst(F,d,/,divd);
398 break;
399 case DIV+I:
400 identity(r,l,I,i,1);
401 if (r->op == CNST+I && r->u.v.i == 0
402 || l->op == CNST+I && l->u.v.i == ty->u.sym->u.limits.min.i
403 && r->op == CNST+I && r->u.v.i == -1)
404 break;
405 xfoldcnst(I,i,/,divi);
406 break;
407 case DIV+U:
408 identity(r,l,U,u,1);
409 if (r->op == CNST+U && r->u.v.u == 0)
410 break;
411 if (r->op == CNST+U && (n = ispow2(r->u.v.u)) != 0)
412 return simplify(RSH, ty, l, cnsttree(inttype, (long)n));
413 foldcnst(U,u,/);
414 break;
415 case EQ+F:
416 cfoldcnst(F,d,==);
417 commute(r,l);
418 break;
419 case EQ+U:
420 cfoldcnst(U,u,==);
421 commute(r,l);
422 zerofield(EQ,U,u);
423 break;
424 case GE+F: cfoldcnst(F,d,>=); break;
425 case GE+I: cfoldcnst(I,i,>=); break;
426 case GE+U:
427 geu(l,r,1); /* l >= 0 => (l,1) */
428 cfoldcnst(U,u,>=);
429 if (l->op == CNST+U && l->u.v.u == 0) /* 0 >= r => r == 0 */
430 return eqtree(EQ, r, l);
431 break;
432 case GT+F: cfoldcnst(F,d, >); break;
433 case GT+I: cfoldcnst(I,i, >); break;
434 case GT+U:
435 geu(r,l,0); /* 0 > r => (r,0) */
436 cfoldcnst(U,u, >);
437 if (r->op == CNST+U && r->u.v.u == 0) /* l > 0 => l != 0 */
438 return eqtree(NE, l, r);
439 break;
440 case LE+F: cfoldcnst(F,d,<=); break;
441 case LE+I: cfoldcnst(I,i,<=); break;
442 case LE+U:
443 geu(r,l,1); /* 0 <= r => (r,1) */
444 cfoldcnst(U,u,<=);
445 if (r->op == CNST+U && r->u.v.u == 0) /* l <= 0 => l == 0 */
446 return eqtree(EQ, l, r);
447 break;
448 case LSH+I:
449 identity(r,l,I,i,0);
450 if (l->op == CNST+I && r->op == CNST+I
451 && r->u.v.i >= 0 && r->u.v.i < 8*l->type->size
452 && muli(l->u.v.i, 1<<r->u.v.i, ty->u.sym->u.limits.min.i, ty->u.sym->u.limits.max.i, needconst))
453 return cnsttree(ty, (long)(l->u.v.i<<r->u.v.i));
454 if (r->op == CNST+I && (r->u.v.i >= 8*ty->size || r->u.v.i < 0)) {
455 warning("shifting an `%t' by %d bits is undefined\n", ty, r->u.v.i);
456 break;
459 break;
460 case LSH+U:
461 identity(r,l,I,i,0);
462 sfoldcnst(<<);
463 if (r->op == CNST+I && (r->u.v.i >= 8*ty->size || r->u.v.i < 0)) {
464 warning("shifting an `%t' by %d bits is undefined\n", ty, r->u.v.i);
465 break;
468 break;
470 case LT+F: cfoldcnst(F,d, <); break;
471 case LT+I: cfoldcnst(I,i, <); break;
472 case LT+U:
473 geu(l,r,0); /* l < 0 => (l,0) */
474 cfoldcnst(U,u, <);
475 if (l->op == CNST+U && l->u.v.u == 0) /* 0 < r => r != 0 */
476 return eqtree(NE, r, l);
477 break;
478 case MOD+I:
479 if (r->op == CNST+I && r->u.v.i == 0
480 || l->op == CNST+I && l->u.v.i == ty->u.sym->u.limits.min.i
481 && r->op == CNST+I && r->u.v.i == -1)
482 break;
483 xfoldcnst(I,i,%,divi);
484 if (r->op == CNST+I && r->u.v.i == 1) /* l%1 => (l,0) */
485 return tree(RIGHT, ty, root(l), cnsttree(ty, 0L));
486 break;
487 case MOD+U:
488 if (r->op == CNST+U && ispow2(r->u.v.u)) /* l%2^n => l&(2^n-1) */
489 return bittree(BAND, l, cnsttree(ty, r->u.v.u - 1));
490 if (r->op == CNST+U && r->u.v.u == 0)
491 break;
492 foldcnst(U,u,%);
493 break;
494 case MUL+F:
495 xfoldcnst(F,d,*,muld);
496 commute(l,r);
497 break;
498 case MUL+I:
499 commute(l,r);
500 xfoldcnst(I,i,*,muli);
501 if (l->op == CNST+I && r->op == ADD+I && r->kids[1]->op == CNST+I)
502 /* c1*(x + c2) => c1*x + c1*c2 */
503 return simplify(ADD, ty, simplify(MUL, ty, l, r->kids[0]),
504 simplify(MUL, ty, l, r->kids[1]));
505 if (l->op == CNST+I && r->op == SUB+I && r->kids[1]->op == CNST+I)
506 /* c1*(x - c2) => c1*x - c1*c2 */
507 return simplify(SUB, ty, simplify(MUL, ty, l, r->kids[0]),
508 simplify(MUL, ty, l, r->kids[1]));
509 if (l->op == CNST+I && l->u.v.i > 0 && (n = ispow2(l->u.v.i)) != 0)
510 /* 2^n * r => r<<n */
511 return simplify(LSH, ty, r, cnsttree(inttype, (long)n));
512 identity(r,l,I,i,1);
513 break;
514 case NE+F:
515 cfoldcnst(F,d,!=);
516 commute(r,l);
517 break;
518 case NE+U:
519 cfoldcnst(U,u,!=);
520 commute(r,l);
521 zerofield(NE,U,u);
522 break;
523 case NEG+F:
524 ufoldcnst(F,cnsttree(ty, -l->u.v.d));
525 idempotent(NEG+F);
526 break;
527 case NEG+I:
528 if (l->op == CNST+I) {
529 if (needconst && l->u.v.i == ty->u.sym->u.limits.min.i)
530 warning("overflow in constant expression\n");
531 if (needconst || l->u.v.i != ty->u.sym->u.limits.min.i)
532 return cnsttree(ty, -l->u.v.i);
534 idempotent(NEG+I);
535 break;
536 case NOT+I:
537 op = NOT;
538 ufoldcnst(I,cnsttree(ty, !l->u.v.i));
539 break;
540 case RSH+I:
541 identity(r,l,I,i,0);
542 if (l->op == CNST+I && r->op == CNST+I
543 && r->u.v.i >= 0 && r->u.v.i < 8*l->type->size) {
544 long n = l->u.v.i>>r->u.v.i;
545 if (l->u.v.i < 0)
546 n |= ~0UL<<(8*l->type->size - r->u.v.i);
547 return cnsttree(ty, n);
549 if (r->op == CNST+I && (r->u.v.i >= 8*ty->size || r->u.v.i < 0)) {
550 warning("shifting an `%t' by %d bits is undefined\n", ty, r->u.v.i);
551 break;
554 break;
555 case RSH+U:
556 identity(r,l,I,i,0);
557 sfoldcnst(>>);
558 if (r->op == CNST+I && (r->u.v.i >= 8*ty->size || r->u.v.i < 0)) {
559 warning("shifting an `%t' by %d bits is undefined\n", ty, r->u.v.i);
560 break;
563 break;
564 case SUB+F:
565 xfoldcnst(F,d,-,subd);
566 break;
567 case SUB+I:
568 xfoldcnst(I,i,-,subi);
569 identity(r,l,I,i,0);
570 break;
571 case SUB+U:
572 foldcnst(U,u,-);
573 identity(r,l,U,u,0);
574 break;
575 case SUB+P:
576 if (l->op == CNST+P && r->op == CNST+P)
577 return cnsttree(ty, (long)((char *)l->u.v.p - (char *)r->u.v.p));
578 if (r->op == CNST+I || r->op == CNST+U)
579 return simplify(ADD, ty, l,
580 cnsttree(inttype, r->op == CNST+I ? -r->u.v.i : -(long)r->u.v.u));
581 if (isaddrop(l->op) && r->op == ADD+I && r->kids[1]->op == CNST+I)
582 /* l - (x + c) => l-c - x */
583 return simplify(SUB, ty,
584 simplify(SUB, ty, l, r->kids[1]), r->kids[0]);
585 break;
586 default:assert(0);
588 return tree(op, ty, l, r);
590 /* ispow2 - if u > 1 && u == 2^n, return n, otherwise return 0 */
591 int ispow2(unsigned long u) {
592 int n;
594 if (u > 1 && (u&(u-1)) == 0)
595 for (n = 0; u; u >>= 1, n++)
596 if (u&1)
597 return n;
598 return 0;