1 /* C O N S T A N T E X P R E S S I O N H A N D L I N G */
4 #include "target_sizes.h"
18 long mach_long_sign; /* sign bit of the machine long */
19 long full_mask[MAXSIZE+1];/* full_mask[1] == 0xFF, full_mask[2] == 0xFFFF, .. */
20 arith max_int; /* maximum integer on the target machine */
21 arith min_int; /* mimimum integer on the target machin */
22 char *maxint_str; /* string representation of maximum integer */
23 arith wrd_bits; /* number of bits in a word */
24 arith max_intset; /* largest value of set of integer */
29 node_warning(expp, "overflow in constant expression");
33 register struct node *expp;
35 /* The unary operation in "expp" is performed on the constant
36 expression below it, and the result restored in expp.
38 register arith o1 = expp->nd_right->nd_INT;
40 switch( expp->nd_symb ) {
41 /* Should not get here
59 expp->nd_class = Value;
60 expp->nd_token = expp->nd_right->nd_token;
63 FreeNode(expp->nd_right);
64 expp->nd_right = NULLNODE;
68 register struct node *expp;
70 /* The binary operation in "expp" is performed on the constant
71 expressions below it, and the result restored in expp.
73 register arith o1, o2;
74 register char *s1, *s2;
75 int str = expp->nd_left->nd_type->tp_fund & T_STRINGCONST;
78 o1 = o2 = 0; /* so LINT won't complain */
79 s1 = expp->nd_left->nd_STR;
80 s2 = expp->nd_right->nd_STR;
83 s1 = s2 = (char *) 0; /* so LINT won't complain */
84 o1 = expp->nd_left->nd_INT;
85 o2 = expp->nd_right->nd_INT;
88 assert(expp->nd_class == Boper);
89 assert(expp->nd_left->nd_class == Value);
90 assert(expp->nd_right->nd_class == Value);
92 switch( expp->nd_symb ) {
94 if (o1 > 0 && o2 > 0) {
95 if (max_int - o1 < o2) overflow(expp);
97 else if (o1 < 0 && o2 < 0) {
98 if (min_int - o1 > o2) overflow(expp);
104 if ( o1 >= 0 && o2 < 0) {
105 if (max_int + o2 < o1) overflow(expp);
107 else if (o1 < 0 && o2 >= 0) {
108 if (min_int + o2 > o1) overflow(expp);
114 if (o1 > 0 && o2 > 0) {
115 if (max_int / o1 < o2) overflow(expp);
117 else if (o1 < 0 && o2 < 0) {
118 if (o1 == min_int || o2 == min_int ||
119 max_int / (-o1) < (-o2)) overflow(expp);
122 if (min_int / o1 > o2) overflow(expp);
125 if (min_int / o2 > o1) overflow(expp);
132 node_error(expp, "division by 0");
140 node_error(expp, "modulo by 0");
156 o1 = str ? !strcmp(s1, s2) : (o1 == o2);
160 o1 = str ? (strcmp(s1, s2) != 0) : (o1 != o2);
164 o1 = str ? (strcmp(s1, s2) <= 0) : (o1 <= o2);
168 o1 = str ? (strcmp(s1, s2) >= 0) : (o1 >= o2);
172 o1 = str ? (strcmp(s1, s2) < 0) : (o1 < o2);
176 o1 = str ? (strcmp(s1, s2) > 0) : (o1 > o2);
185 expp->nd_class = Value;
186 expp->nd_token = expp->nd_right->nd_token;
187 /* STRING compare has a bool_type as result */
188 if( expp->nd_type == bool_type ) expp->nd_symb = INTEGER;
191 FreeNode(expp->nd_left);
192 FreeNode(expp->nd_right);
193 expp->nd_left = expp->nd_right = NULLNODE;
197 register struct node *expp;
199 register arith *set1, *set2;
200 arith *resultset = (arith *) 0;
201 int empty_result = 0;
202 register int setsize, j;
204 assert(expp->nd_right->nd_class == Set);
205 assert(expp->nd_symb == IN || expp->nd_left->nd_class == Set);
206 set2 = expp->nd_right->nd_set;
207 setsize = (unsigned) (expp->nd_right->nd_type->tp_size) / (unsigned) word_size;
209 if( expp->nd_symb == IN ) {
212 assert(expp->nd_left->nd_class == Value);
214 i = expp->nd_left->nd_INT;
215 expp->nd_class = Value;
216 expp->nd_symb = INTEGER;
218 expp->nd_INT = (i >= 0 && set2 && i < (setsize * wrd_bits) &&
219 (set2[i/wrd_bits] & (1 << (i%wrd_bits))));
221 if( set2 ) free((char *) set2);
224 set1 = expp->nd_left->nd_set;
226 expp->nd_left->nd_set = (arith *) 0;
227 switch( expp->nd_symb ) {
233 expp->nd_right->nd_set = (arith *) 0;
237 for( j = 0; j < setsize; j++ )
244 if( !set1 || !set2 ) {
245 /* The set from which something is substracted
246 is already empty, or the set that is
247 substracted is empty. In either case, the
253 for( j = 0; j < setsize; j++ )
254 if( *set1++ &= ~*set2++ ) empty_result = 0;
261 /* set1 is empty, and so is the result set
266 /* set 2 is empty, so the result set must be
270 expp->nd_right->nd_set = (arith *) 0;
274 for( j = 0; j < setsize; j++ )
275 if( *set1++ &= *set2++ ) empty_result = 0;
282 /* Constant set comparisons
284 if( !setsize ) setsize++; /* force comparison */
285 expp->nd_left->nd_set = set1; /* may be disposed of */
286 for( j = 0; j < setsize; j++ ) {
287 switch( expp->nd_symb ) {
290 if( !set1 && !set2 ) {
294 if( !set1 || !set2 ) break;
295 if( *set1++ != *set2++ ) break;
303 if( (*set2 | *set1++) != *set2 ) break;
312 if( (*set1 | *set2++) != *set1 ) break;
319 expp->nd_INT = expp->nd_symb == NOTEQUAL;
321 expp->nd_INT = expp->nd_symb != NOTEQUAL;
322 expp->nd_class = Value;
323 expp->nd_symb = INTEGER;
324 if( expp->nd_left->nd_set )
325 free((char *) expp->nd_left->nd_set);
326 if( expp->nd_right->nd_set )
327 free((char *) expp->nd_right->nd_set);
328 FreeNode(expp->nd_left);
329 FreeNode(expp->nd_right);
330 expp->nd_left = expp->nd_right = NULLNODE;
335 if( expp->nd_right->nd_set )
336 free((char *) expp->nd_right->nd_set);
337 if( expp->nd_left->nd_set )
338 free((char *) expp->nd_left->nd_set);
340 free((char *) resultset);
341 resultset = (arith *) 0;
343 expp->nd_class = Set;
344 expp->nd_set = resultset;
346 FreeNode(expp->nd_left);
347 FreeNode(expp->nd_right);
348 expp->nd_left = expp->nd_right = NULLNODE;
352 register struct node *expp;
354 /* a standard procedure call is found that can be evaluated
355 compile time, so do so.
357 register struct node *expr = NULLNODE;
359 assert(expp->nd_class == Call);
361 expr = expp->nd_right->nd_left;
363 expp->nd_class = Value;
364 expp->nd_symb = INTEGER;
367 if( expr->nd_INT < 0 ) {
368 if (expr->nd_INT <= min_int) {
371 expp->nd_INT = - expr->nd_INT;
373 else expp->nd_INT = expr->nd_INT;
378 if (expr->nd_INT < 0) {
379 if ( expr->nd_INT == min_int ||
380 max_int / expr->nd_INT > expr->nd_INT) {
384 else if (max_int / expr->nd_INT < expr->nd_INT) {
387 expp->nd_INT = expr->nd_INT * expr->nd_INT;
393 expp->nd_INT = expr->nd_INT;
398 expp->nd_INT = (expr->nd_INT & 1);
402 expp->nd_INT = expr->nd_INT + 1;
403 if( /* Check overflow of subranges or enumerations */
404 (expp->nd_type->tp_fund & T_SUBRANGE &&
405 expp->nd_INT > expp->nd_type->sub_ub
408 ( expp->nd_type->tp_fund & T_ENUMERATION &&
409 expp->nd_INT >= expp->nd_type->enm_ncst
412 node_warning(expp, "\"succ\": no successor");
417 expp->nd_INT = expr->nd_INT - 1;
418 if( /* Check with lowerbound of subranges or enumerations */
419 (expp->nd_type->tp_fund & T_SUBRANGE &&
420 expp->nd_INT < expp->nd_type->sub_lb
423 ( expp->nd_type->tp_fund & T_ENUMERATION &&
427 node_warning(expp, "\"pred\": no predecessor");
434 FreeNode(expp->nd_left);
435 FreeNode(expp->nd_right);
436 expp->nd_right = expp->nd_left = NULLNODE;
440 register struct node *expr;
442 /* The constant value of the expression expr is made to conform
443 * to the size of the type of the expression
445 register arith o1 = expr->nd_INT;
446 register struct type *tp = BaseType(expr->nd_type);
447 int size = tp->tp_size;
448 long remainder = o1 & ~full_mask[size];
450 assert(expr->nd_class == Value);
452 if( tp->tp_fund & T_CHAR ) {
453 if( o1 & (~full_mask[size] >> 1) ) {
454 node_warning(expr, "overflow in character value");
458 else if( remainder != 0 && remainder != ~full_mask[size] ||
459 (o1 & full_mask[size]) == 1 << (size * 8 - 1) ) {
460 /* integers in [-maxint .. maxint] */
461 int nbits = (int) (sizeof(long) - size) * 8;
463 /* overflow(expr); */
464 /* sign bit of o1 in sign bit of mach_long */
466 /* shift back to get sign extension */
474 extern char *long2str(), *Salloc();
476 register arith bt = (arith)0;
479 bt = (bt << 8) + 0377;
481 if( i == MAXSIZE + 1 )
482 fatal("array full_mask too small for this machine");
485 mach_long_sign = 1L << (sizeof(long) * 8 - 1);
486 if( int_size > sizeof(long) )
487 fatal("sizeof (long) insufficient on this machine");
489 max_int = full_mask[int_size] & ~(1L << (int_size * 8 - 1));
491 maxint_str = long2str(max_int, 10);
492 maxint_str = Salloc(maxint_str, (unsigned int) strlen(maxint_str));
493 wrd_bits = 8 * (int) word_size;
494 if( !max_intset ) max_intset = wrd_bits - 1;