|
|
1.1 root 1: /*
2: * This file contains the mini
3: * constant expression folder used by the
4: * parser. More of this is done in the
5: * code generator. This one exists only to
6: * allow constant expressions in case labels
7: * and in array bounds.
8: */
9: #ifdef vax
10: #include "INC$LIB:cc0.h"
11: #else
12: #include "cc0.h"
13: #endif
14:
15: /*
16: * Try to fold.
17: * Return pointer to a constant tree
18: * node, or NULL if folding is impossible.
19: */
20: TREE *
21: fold0(op, lp, rp)
22: TREE *lp, *rp;
23: {
24: register TREE *tp;
25: register lrf, zrf, sop;
26: lval_t c1, c2, grablval();
27:
28: lrf = zrf = 0;
29: sop = lp->t_op;
30: if (sop == LCON)
31: ++lrf;
32: else if (sop == ZCON)
33: ++zrf;
34: else if (sop != ICON || lp->t_dp != NULL)
35: return NULL;
36: c1 = grablval(lp);
37: if (op == QUEST) {
38: if (rp->t_op != COLON)
39: return (NULL);
40: return (c1 ? rp->t_lp : rp->t_rp);
41: }
42: if (rp != NULL) {
43: sop = rp->t_op;
44: if (sop == LCON)
45: ++lrf;
46: else if (sop == ZCON)
47: ++zrf;
48: else if (sop != ICON || rp->t_dp != NULL)
49: return NULL;
50: c2 = grablval(rp);
51: }
52: switch (op) {
53:
54: case COM:
55: c1 = ~c1;
56: break;
57:
58: case NOT:
59: c1 = !c1;
60: break;
61:
62: case NEG:
63: c1 = -c1;
64: break;
65:
66: case ADD:
67: c1 += c2;
68: break;
69:
70: case SUB:
71: c1 -= c2;
72: break;
73:
74: case MUL:
75: c1 *= c2;
76: break;
77:
78: case DIV:
79: if (c2 == 0) {
80: cwarn("divide by zero");
81: return (NULL);
82: }
83: c1 /= c2;
84: break;
85:
86: case REM:
87: if (c2 == 0) {
88: cwarn("zero modulus");
89: return (NULL);
90: }
91: c1 %= c2;
92: break;
93:
94: case AND:
95: c1 &= c2;
96: break;
97:
98: case OR:
99: c1 |= c2;
100: break;
101:
102: case XOR:
103: c1 ^= c2;
104: break;
105:
106: case SHL:
107: c1 <<= c2;
108: break;
109:
110: case SHR:
111: c1 >>= c2;
112: break;
113:
114: case EQ:
115: c1 = c1==c2;
116: break;
117:
118: case NE:
119: c1 = c1!=c2;
120: break;
121:
122: case LT:
123: c1 = c1<c2;
124: break;
125:
126: case LE:
127: c1 = c1<=c2;
128: break;
129:
130: case GT:
131: c1 = c1>c2;
132: break;
133:
134: case GE:
135: c1 = c1>=c2;
136: break;
137:
138: case ANDAND:
139: c1 = (c1 && c2);
140: lrf = 0;
141: break;
142:
143: case OROR:
144: c1 = (c1 || c2);
145: lrf = 0;
146: break;
147:
148: default:
149: return (NULL);
150: }
151: tp = talloc();
152: if (lrf) {
153: tp->t_op = LCON;
154: tp->t_type = T_LONG;
155: tp->t_lval = c1;
156: return (tp);
157: }
158: if (zrf) {
159: tp->t_op = ZCON;
160: tp->t_type = T_UINT;
161: tp->t_lval = c1;
162: return (tp);
163: }
164: tp->t_op = ICON;
165: tp->t_type = T_INT;
166: tp->t_ival = c1;
167: return (tp);
168: }
169:
170: /*
171: * Grab the value of a
172: * constant (ICON or LCON) node.
173: * Look at the type of the node if ICON
174: * and 0 extend if necessary.
175: */
176: lval_t
177: grablval(tp)
178: register TREE *tp;
179: {
180: register op, t;
181:
182: if ((op=tp->t_op) == ICON) {
183: if (tp->t_dp != NULL
184: || (t=tp->t_type) == T_UCHAR
185: || t == T_USHORT
186: || t == T_UINT)
187: return ((unsigned) tp->t_ival);
188: return (tp->t_ival);
189: }
190: if (op == ZCON)
191: return (tp->t_zval);
192: if (op == LCON)
193: return (tp->t_lval);
194: cbotch("grablval");
195: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.