stage3/constant_folding.cc
changeset 574 d291a942899b
parent 573 e28b47911c19
child 575 a1b63f776535
equal deleted inserted replaced
573:e28b47911c19 574:d291a942899b
    29  * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
    29  * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
    30  *
    30  *
    31  */
    31  */
    32 
    32 
    33 
    33 
    34 /* NOTE:
       
    35  *   Most of the conditions to detect overflows on signed (but not unsigned) integer operations were adapted from
       
    36  *   https://www.securecoding.cert.org/confluence/display/seccode/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow?showComments=false
       
    37  */
       
    38 
    34 
    39 
    35 
    40 
    36 
    41 /* Do constant folding...
    37 /* Do constant folding...
    42  *
    38  *
   124 #include <limits>
   120 #include <limits>
   125 #include <math.h> /* required for pow function */
   121 #include <math.h> /* required for pow function */
   126 #include <stdlib.h> /* required for malloc() */
   122 #include <stdlib.h> /* required for malloc() */
   127 
   123 
   128 #if 1
   124 #if 1
   129 #define INT64_MAX (std::numeric_limits< int64_t >::max())
   125 #define UINT64_MAX (std::numeric_limits< uint64_t >::max())
   130 #define INT64_MIN (std::numeric_limits< int64_t >::min()) 
   126 #define  INT64_MAX (std::numeric_limits<  int64_t >::max())
       
   127 #define  INT64_MIN (std::numeric_limits<  int64_t >::min()) 
   131 #else
   128 #else
   132 /* An alternative is to use the std::numeric_limits< uint64_t >::min() / max()  methods already defined in #include <limits> */
       
   133 #define __STDC_LIMIT_MACROS /* required for UINT64_MAX, INT64_MAX, INT64_MIN, ... */
   129 #define __STDC_LIMIT_MACROS /* required for UINT64_MAX, INT64_MAX, INT64_MIN, ... */
   134 #include <stdint.h>         /* required for UINT64_MAX, INT64_MAX, INT64_MIN, ... */
   130 #include <stdint.h>         /* required for UINT64_MAX, INT64_MAX, INT64_MIN, ... */
   135 #endif
   131 #endif
   136 
   132 
   137 
   133 
   179 #define GET_CVALUE(dtype, symbol)             ((symbol)->const_value_##dtype->value) 
   175 #define GET_CVALUE(dtype, symbol)             ((symbol)->const_value_##dtype->value) 
   180 #define SET_OVFLOW(dtype, symbol)             ((symbol)->const_value_##dtype->status) = symbol_c::cs_overflow
   176 #define SET_OVFLOW(dtype, symbol)             ((symbol)->const_value_##dtype->status) = symbol_c::cs_overflow
   181     /* The following test is correct in the presence of a NULL pointer, as the logical evaluation will be suspended as soon as the first condition is false! */
   177     /* The following test is correct in the presence of a NULL pointer, as the logical evaluation will be suspended as soon as the first condition is false! */
   182 #define VALID_CVALUE(dtype, symbol)           ((NULL != (symbol)->const_value_##dtype) && (symbol_c::cs_const_value == (symbol)->const_value_##dtype->status))
   178 #define VALID_CVALUE(dtype, symbol)           ((NULL != (symbol)->const_value_##dtype) && (symbol_c::cs_const_value == (symbol)->const_value_##dtype->status))
   183 #define ISZERO_CVALUE(dtype, symbol)          ((VALID_CVALUE(dtype, symbol)) && (GET_CVALUE(dtype, symbol) == 0))
   179 #define ISZERO_CVALUE(dtype, symbol)          ((VALID_CVALUE(dtype, symbol)) && (GET_CVALUE(dtype, symbol) == 0))
   184 #define DO_BIN_OPER(dtype, oper)\
   180 #define DO_BINARY_OPER(dtype, oper)\
   185 	if (VALID_CVALUE(dtype, symbol->r_exp) && VALID_CVALUE(dtype, symbol->l_exp)) {                                \
   181 	if (VALID_CVALUE(dtype, symbol->r_exp) && VALID_CVALUE(dtype, symbol->l_exp)) {                                \
   186 		NEW_CVALUE(dtype, symbol);                                                                             \
   182 		NEW_CVALUE(dtype, symbol);                                                                             \
   187 		SET_CVALUE(dtype, symbol, GET_CVALUE(dtype, symbol->l_exp) oper GET_CVALUE(dtype, symbol->r_exp));     \
   183 		SET_CVALUE(dtype, symbol, GET_CVALUE(dtype, symbol->l_exp) oper GET_CVALUE(dtype, symbol->r_exp));     \
   188 	}
   184 	}
   189 
   185 
   192 
   188 
   193 
   189 
   194 
   190 
   195 
   191 
   196 
   192 
   197 
   193 /* NOTE:
   198 
   194  *   Most of the conditions to detect overflows on signed and unsigned integer operations were adapted from
       
   195  *   https://www.securecoding.cert.org/confluence/display/seccode/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow?showComments=false
       
   196  *   https://www.securecoding.cert.org/confluence/display/seccode/INT30-C.+Ensure+that+unsigned+integer+operations+do+not+wrap
       
   197  */
       
   198 
       
   199 /* NOTE: If at all possible, all overflow tests are done by pre-condition tests, i.e. tests that 
       
   200  *       can be run _before_ the operation is executed, and therefore without accessing the result!
       
   201  *
       
   202  *       The exception is for real/floating point values, that simply test if the result is NaN (not a number).
       
   203  */
   199 
   204 
   200 /* res = a + b */
   205 /* res = a + b */
   201 static void CHECK_OVERFLOW_uint64_SUM(symbol_c *res, symbol_c *a, symbol_c *b) {
   206 static void CHECK_OVERFLOW_uint64_SUM(symbol_c *res, symbol_c *a, symbol_c *b) {
   202 	if (VALID_CVALUE(uint64, res))
   207 	if (!VALID_CVALUE(uint64, res))
   203 		/* If sum is smaller than either operand => overflow! */
   208 		return;
   204 		if (GET_CVALUE(uint64, res) < GET_CVALUE(uint64, a))
   209 	/* Test by post-condition: If sum is smaller than either operand => overflow! */
   205 			SET_OVFLOW(uint64, res);
   210 	// if (GET_CVALUE(uint64, res) < GET_CVALUE(uint64, a))
   206 }
   211 	/* Test by pre-condition: If (UINT64_MAX - a) < b => overflow! */
       
   212 	if ((UINT64_MAX - GET_CVALUE(uint64, a)) < GET_CVALUE(uint64, b))
       
   213 		SET_OVFLOW(uint64, res);
       
   214 }
       
   215 
   207 
   216 
   208 /* res = a - b */
   217 /* res = a - b */
   209 static void CHECK_OVERFLOW_uint64_SUB(symbol_c *res, symbol_c *a, symbol_c *b) {
   218 static void CHECK_OVERFLOW_uint64_SUB(symbol_c *res, symbol_c *a, symbol_c *b) {
   210 	if (VALID_CVALUE(uint64, res))
   219 	if (!VALID_CVALUE(uint64, res))
   211 		/* If diference is larger than a => overflow! */
   220 		return;
   212 		if (GET_CVALUE(uint64, res) > GET_CVALUE(uint64, a))
   221 	/* Test by post-condition: If diference is larger than a => overflow! */
   213 			SET_OVFLOW(uint64, res);
   222 	// if (GET_CVALUE(uint64, res) > GET_CVALUE(uint64, a))
   214 }
   223 	/* Test by pre-condition: if b > a => overflow! */
       
   224 	if (GET_CVALUE(uint64, b) > GET_CVALUE(uint64, a))
       
   225 		SET_OVFLOW(uint64, res);
       
   226 }
       
   227 
   215 
   228 
   216 /* res = a * b */
   229 /* res = a * b */
   217 static void CHECK_OVERFLOW_uint64_MUL(symbol_c *res, symbol_c *a, symbol_c *b) {
   230 static void CHECK_OVERFLOW_uint64_MUL(symbol_c *res, symbol_c *a, symbol_c *b) {
   218 	if (VALID_CVALUE(uint64, res))
   231 	if (!VALID_CVALUE(uint64, res))
   219 		if (false /* TODO */)
   232 		return;
   220 			SET_OVFLOW(uint64, res);
   233 	/* Test by pre-condition: If (UINT64_MAX / a) < b => overflow! */
   221 }
   234 	if ((UINT64_MAX / GET_CVALUE(uint64, a)) < GET_CVALUE(uint64, b))
       
   235 		SET_OVFLOW(uint64, res);
       
   236 }
       
   237 
   222 
   238 
   223 /* res = a / b */
   239 /* res = a / b */
   224 static void CHECK_OVERFLOW_uint64_DIV(symbol_c *res, symbol_c *a, symbol_c *b) {
   240 static void CHECK_OVERFLOW_uint64_DIV(symbol_c *res, symbol_c *a, symbol_c *b) {
   225 	if (VALID_CVALUE(uint64, res))
   241 	if (!VALID_CVALUE(uint64, res))
   226 		if (false /* TODO */)
   242 		return;
   227 			SET_OVFLOW(uint64, res);
   243 	if (GET_CVALUE(uint64, b) == 0) /* division by zero! */
   228 }
   244 		SET_OVFLOW(uint64, res);
       
   245 }
       
   246 
   229 
   247 
   230 /* res = a MOD b */
   248 /* res = a MOD b */
   231 static void CHECK_OVERFLOW_uint64_MOD(symbol_c *res, symbol_c *a, symbol_c *b) {
   249 static void CHECK_OVERFLOW_uint64_MOD(symbol_c *res, symbol_c *a, symbol_c *b) {
   232 	if (VALID_CVALUE(uint64, res))
   250 	if (!VALID_CVALUE(uint64, res))
   233 		if (false /* TODO */)
   251 		return;
   234 			SET_OVFLOW(uint64, res);
   252 	/* no overflow condition exists, including division by zero, which IEC 61131-3 considers legal for MOD operation! */
   235 }
   253 	if (false) 
       
   254 		SET_OVFLOW(uint64, res);
       
   255 }
       
   256 
   236 
   257 
   237 /* res = a + b */
   258 /* res = a + b */
   238 static void CHECK_OVERFLOW_int64_SUM(symbol_c *res, symbol_c *a_ptr, symbol_c *b_ptr) {
   259 static void CHECK_OVERFLOW_int64_SUM(symbol_c *res, symbol_c *a_ptr, symbol_c *b_ptr) {
       
   260 	if (!VALID_CVALUE(int64, res))
       
   261 		return;
   239 	int64_t a = GET_CVALUE(int64, a_ptr);
   262 	int64_t a = GET_CVALUE(int64, a_ptr);
   240 	int64_t b = GET_CVALUE(int64, b_ptr);
   263 	int64_t b = GET_CVALUE(int64, b_ptr);
   241 	if (VALID_CVALUE(int64, res))
   264 	/* The following test is valid no matter what representation is being used (e.g. two's complement, etc...) */
   242 		/* The following test is valid no matter what representation is being used (e.g. two's complement, etc...) */
   265 	if (((b > 0) && (a > (INT64_MAX - b)))
   243 		if (((b > 0) && (a > (INT64_MAX - b)))
   266 	 || ((b < 0) && (a < (INT64_MIN - b))))
   244 		 || ((b < 0) && (a < (INT64_MIN - b))))
   267 		SET_OVFLOW(int64, res);
   245 			SET_OVFLOW(int64, res);
   268 }
   246 }
   269 
   247 
   270 
   248 /* res = a - b */
   271 /* res = a - b */
   249 static void CHECK_OVERFLOW_int64_SUB(symbol_c *res, symbol_c *a_ptr, symbol_c *b_ptr) {
   272 static void CHECK_OVERFLOW_int64_SUB(symbol_c *res, symbol_c *a_ptr, symbol_c *b_ptr) {
       
   273 	if (!VALID_CVALUE(int64, res))
       
   274 		return;
   250 	int64_t a = GET_CVALUE(int64, a_ptr);
   275 	int64_t a = GET_CVALUE(int64, a_ptr);
   251 	int64_t b = GET_CVALUE(int64, b_ptr);
   276 	int64_t b = GET_CVALUE(int64, b_ptr);
   252 	if (VALID_CVALUE(int64, res))
   277 	/* The following test is valid no matter what representation is being used (e.g. two's complement, etc...) */
   253 		/* The following test is valid no matter what representation is being used (e.g. two's complement, etc...) */
   278 	if (((b > 0) && (a < (INT64_MIN + b)))
   254 		if (((b > 0) && (a < (INT64_MIN + b)))
   279 	 || ((b < 0) && (a > (INT64_MAX + b))))
   255 		 || ((b < 0) && (a > (INT64_MAX + b))))
   280 		SET_OVFLOW(int64, res);
   256 			SET_OVFLOW(int64, res);
       
   257 }
   281 }
   258 
   282 
   259 
   283 
   260 /* res = a * b */
   284 /* res = a * b */
   261 static void CHECK_OVERFLOW_int64_MUL(symbol_c *res, symbol_c *a_ptr, symbol_c *b_ptr) {
   285 static void CHECK_OVERFLOW_int64_MUL(symbol_c *res, symbol_c *a_ptr, symbol_c *b_ptr) {
       
   286 	if (!VALID_CVALUE(int64, res))
       
   287 		return;
   262 	int64_t a = GET_CVALUE(int64, a_ptr);
   288 	int64_t a = GET_CVALUE(int64, a_ptr);
   263 	int64_t b = GET_CVALUE(int64, b_ptr);
   289 	int64_t b = GET_CVALUE(int64, b_ptr);
   264 	if (VALID_CVALUE(int64, res))
   290 	if (   ( (a > 0) &&  (b > 0) &&             (a > (INT64_MAX / b))) 
   265 		if (   ( (a > 0) &&  (b > 0) &&             (a > (INT64_MAX / b))) 
   291 	    || ( (a > 0) && !(b > 0) &&             (b < (INT64_MIN / a))) 
   266 		    || ( (a > 0) && !(b > 0) &&             (b < (INT64_MIN / a))) 
   292 	    || (!(a > 0) &&  (b > 0) &&             (a < (INT64_MIN / b))) 
   267 		    || (!(a > 0) &&  (b > 0) &&             (a < (INT64_MIN / b))) 
   293 	    || (!(a > 0) && !(b > 0) && (a != 0) && (b < (INT64_MAX / a))))
   268 		    || (!(a > 0) && !(b > 0) && (a != 0) && (b < (INT64_MAX / a))))
   294 		SET_OVFLOW(int64, res);
   269 			SET_OVFLOW(int64, res);
       
   270 }
   295 }
   271 
   296 
   272 
   297 
   273 /* res = a / b */
   298 /* res = a / b */
   274 static void CHECK_OVERFLOW_int64_DIV(symbol_c *res, symbol_c *a_ptr, symbol_c *b_ptr) {
   299 static void CHECK_OVERFLOW_int64_DIV(symbol_c *res, symbol_c *a_ptr, symbol_c *b_ptr) {
       
   300 	if (!VALID_CVALUE(int64, res))
       
   301 		return;
   275 	int64_t a = GET_CVALUE(int64, a_ptr);
   302 	int64_t a = GET_CVALUE(int64, a_ptr);
   276 	int64_t b = GET_CVALUE(int64, b_ptr);
   303 	int64_t b = GET_CVALUE(int64, b_ptr);
   277 	if (VALID_CVALUE(int64, res))
   304 	if ((b == 0) || ((a == INT64_MIN) && (b == -1)))
   278 		if ((b == 0) || ((a == INT64_MIN) && (b == -1)))
   305 		SET_OVFLOW(int64, res);
   279 			SET_OVFLOW(int64, res);
       
   280 }
   306 }
   281 
   307 
   282 
   308 
   283 /* res = a MOD b */
   309 /* res = a MOD b */
   284 static void CHECK_OVERFLOW_int64_MOD(symbol_c *res, symbol_c *a_ptr, symbol_c *b_ptr) {
   310 static void CHECK_OVERFLOW_int64_MOD(symbol_c *res, symbol_c *a_ptr, symbol_c *b_ptr) {
       
   311 	if (!VALID_CVALUE(int64, res))
       
   312 		return;
   285 	int64_t a = GET_CVALUE(int64, a_ptr);
   313 	int64_t a = GET_CVALUE(int64, a_ptr);
   286 	int64_t b = GET_CVALUE(int64, b_ptr);
   314 	int64_t b = GET_CVALUE(int64, b_ptr);
   287 	/* IEC 61131-3 standard says IN1 MOD IN2 must be equivalent to
   315 	/* IEC 61131-3 standard says IN1 MOD IN2 must be equivalent to
   288 	 *  IF (IN2 = 0) THEN OUT:=0 ; ELSE OUT:=IN1 - (IN1/IN2)*IN2 ; END_IF
   316 	 *  IF (IN2 = 0) THEN OUT:=0 ; ELSE OUT:=IN1 - (IN1/IN2)*IN2 ; END_IF
   289 	 *
   317 	 *
   290 	 * Note that, when IN1 = INT64_MIN, and IN2 = -1, an overflow occurs in the division,
   318 	 * Note that, when IN1 = INT64_MIN, and IN2 = -1, an overflow occurs in the division,
   291 	 * so although the MOD operation should be OK, acording to the above definition, we actually have an overflow!!
   319 	 * so although the MOD operation should be OK, acording to the above definition, we actually have an overflow!!
   292 	 *
   320 	 *
   293 	 * On the other hand, division by 0 is OK!!
   321 	 * On the other hand, division by 0 is OK!!
   294 	 */
   322 	 */
   295 	if (VALID_CVALUE(int64, res))
   323 	if ((a == INT64_MIN) && (b == -1))
   296 		if ((a == INT64_MIN) && (b == -1))
   324 		SET_OVFLOW(int64, res);
   297 			SET_OVFLOW(int64, res);
       
   298 }
   325 }
   299 
   326 
   300 
   327 
   301 /* res = - a */
   328 /* res = - a */
   302 static void CHECK_OVERFLOW_int64_NEG(symbol_c *res, symbol_c *a_ptr) {
   329 static void CHECK_OVERFLOW_int64_NEG(symbol_c *res, symbol_c *a_ptr) {
       
   330 	if (!VALID_CVALUE(int64, res))
       
   331 		return;
   303 	int64_t a = GET_CVALUE(int64, a_ptr);
   332 	int64_t a = GET_CVALUE(int64, a_ptr);
   304 	if (VALID_CVALUE(int64, res))
   333 	if (a == INT64_MIN)
   305 		if (a == INT64_MIN)
   334 		SET_OVFLOW(int64, res);
   306 			SET_OVFLOW(int64, res);
       
   307 }
   335 }
   308 
   336 
   309 
   337 
   310 
   338 
   311 static void CHECK_OVERFLOW_real64(symbol_c *res) {
   339 static void CHECK_OVERFLOW_real64(symbol_c *res) {
   312 	if (VALID_CVALUE(real64, res))
   340 	if (!VALID_CVALUE(real64, res))
   313         	/* NaN => underflow, overflow, number is a higher precision format, is a complex number (IEEE standard) */
   341 		return;
   314 		 if (isnan(GET_CVALUE(real64, res)))
   342        	/* NaN => underflow, overflow, number is a higher precision format, is a complex number (IEEE standard) */
   315 			SET_OVFLOW(real64, res);
   343 	if (isnan(GET_CVALUE(real64, res)))
       
   344 		SET_OVFLOW(real64, res);
   316 }
   345 }
   317 
   346 
   318 
   347 
   319 
   348 
   320 
   349 
   388 	symbol->exp->accept(*this);
   417 	symbol->exp->accept(*this);
   389 	if (VALID_CVALUE(int64, symbol->exp)) {
   418 	if (VALID_CVALUE(int64, symbol->exp)) {
   390 		NEW_CVALUE( int64, symbol);
   419 		NEW_CVALUE( int64, symbol);
   391 		SET_CVALUE( int64, symbol, - GET_CVALUE( int64, symbol->exp));
   420 		SET_CVALUE( int64, symbol, - GET_CVALUE( int64, symbol->exp));
   392 	}
   421 	}
   393        	CHECK_OVERFLOW_int64_NEG(symbol, symbol->exp);
   422 	CHECK_OVERFLOW_int64_NEG(symbol, symbol->exp);
   394 	return NULL;
   423 	return NULL;
   395 }
   424 }
   396 
   425 
   397 
   426 
   398 void *constant_folding_c::visit(binary_integer_c *symbol) {
   427 void *constant_folding_c::visit(binary_integer_c *symbol) {
   482 /* B 3.1 - Expressions */
   511 /* B 3.1 - Expressions */
   483 /***********************/
   512 /***********************/
   484 void *constant_folding_c::visit(or_expression_c *symbol) {
   513 void *constant_folding_c::visit(or_expression_c *symbol) {
   485 	symbol->l_exp->accept(*this);
   514 	symbol->l_exp->accept(*this);
   486 	symbol->r_exp->accept(*this);
   515 	symbol->r_exp->accept(*this);
   487 	DO_BIN_OPER(bool,   ||);
   516 	DO_BINARY_OPER(bool,   ||);
   488 	DO_BIN_OPER(uint64, | );
   517 	DO_BINARY_OPER(uint64, | );
   489 	return NULL;
   518 	return NULL;
   490 }
   519 }
   491 
   520 
   492 
   521 
   493 void *constant_folding_c::visit(xor_expression_c *symbol) {
   522 void *constant_folding_c::visit(xor_expression_c *symbol) {
   494 	symbol->l_exp->accept(*this);
   523 	symbol->l_exp->accept(*this);
   495 	symbol->r_exp->accept(*this);
   524 	symbol->r_exp->accept(*this);
   496 	DO_BIN_OPER(bool,   ^);
   525 	DO_BINARY_OPER(bool,   ^);
   497 	DO_BIN_OPER(uint64, ^);
   526 	DO_BINARY_OPER(uint64, ^);
   498 	return NULL;
   527 	return NULL;
   499 }
   528 }
   500 
   529 
   501 
   530 
   502 void *constant_folding_c::visit(and_expression_c *symbol) {
   531 void *constant_folding_c::visit(and_expression_c *symbol) {
   503 	symbol->l_exp->accept(*this);
   532 	symbol->l_exp->accept(*this);
   504 	symbol->r_exp->accept(*this);
   533 	symbol->r_exp->accept(*this);
   505 	DO_BIN_OPER(bool,   &&);
   534 	DO_BINARY_OPER(bool,   &&);
   506 	DO_BIN_OPER(uint64, & );
   535 	DO_BINARY_OPER(uint64, & );
   507 	return NULL;
   536 	return NULL;
   508 }
   537 }
   509 
   538 
   510 
   539 
   511 void *constant_folding_c::visit(equ_expression_c *symbol) {
   540 void *constant_folding_c::visit(equ_expression_c *symbol) {
   512 	symbol->l_exp->accept(*this);
   541 	symbol->l_exp->accept(*this);
   513 	symbol->r_exp->accept(*this);
   542 	symbol->r_exp->accept(*this);
   514 	DO_BIN_OPER(bool,   ==);
   543 	DO_BINARY_OPER(bool,   ==);
   515 	DO_BIN_OPER(uint64, ==);
   544 	DO_BINARY_OPER(uint64, ==);
   516 	DO_BIN_OPER( int64, ==);
   545 	DO_BINARY_OPER( int64, ==);
   517 	DO_BIN_OPER(real64, ==);
   546 	DO_BINARY_OPER(real64, ==);
   518 	return NULL;
   547 	return NULL;
   519 }
   548 }
   520 
   549 
   521 
   550 
   522 void *constant_folding_c::visit(notequ_expression_c *symbol) {
   551 void *constant_folding_c::visit(notequ_expression_c *symbol) {
   523 	symbol->l_exp->accept(*this);
   552 	symbol->l_exp->accept(*this);
   524 	symbol->r_exp->accept(*this);
   553 	symbol->r_exp->accept(*this);
   525 	DO_BIN_OPER(bool,   !=);
   554 	DO_BINARY_OPER(bool,   !=);
   526 	DO_BIN_OPER(uint64, !=);
   555 	DO_BINARY_OPER(uint64, !=);
   527 	DO_BIN_OPER( int64, !=);
   556 	DO_BINARY_OPER( int64, !=);
   528 	DO_BIN_OPER(real64, !=);
   557 	DO_BINARY_OPER(real64, !=);
   529 	return NULL;
   558 	return NULL;
   530 }
   559 }
   531 
   560 
   532 
   561 
   533 void *constant_folding_c::visit(lt_expression_c *symbol) {
   562 void *constant_folding_c::visit(lt_expression_c *symbol) {
   534 	symbol->l_exp->accept(*this);
   563 	symbol->l_exp->accept(*this);
   535 	symbol->r_exp->accept(*this);
   564 	symbol->r_exp->accept(*this);
   536 	DO_BIN_OPER(bool,   <);
   565 	DO_BINARY_OPER(bool,   <);
   537 	DO_BIN_OPER(uint64, <);
   566 	DO_BINARY_OPER(uint64, <);
   538 	DO_BIN_OPER( int64, <);
   567 	DO_BINARY_OPER( int64, <);
   539 	DO_BIN_OPER(real64, <);
   568 	DO_BINARY_OPER(real64, <);
   540 	return NULL;
   569 	return NULL;
   541 }
   570 }
   542 
   571 
   543 
   572 
   544 void *constant_folding_c::visit(gt_expression_c *symbol) {
   573 void *constant_folding_c::visit(gt_expression_c *symbol) {
   545 	symbol->l_exp->accept(*this);
   574 	symbol->l_exp->accept(*this);
   546 	symbol->r_exp->accept(*this);
   575 	symbol->r_exp->accept(*this);
   547 	DO_BIN_OPER(bool,   >);
   576 	DO_BINARY_OPER(bool,   >);
   548 	DO_BIN_OPER(uint64, >);
   577 	DO_BINARY_OPER(uint64, >);
   549 	DO_BIN_OPER( int64, >);
   578 	DO_BINARY_OPER( int64, >);
   550 	DO_BIN_OPER(real64, >);
   579 	DO_BINARY_OPER(real64, >);
   551 	return NULL;
   580 	return NULL;
   552 }
   581 }
   553 
   582 
   554 
   583 
   555 void *constant_folding_c::visit(le_expression_c *symbol) {
   584 void *constant_folding_c::visit(le_expression_c *symbol) {
   556 	symbol->l_exp->accept(*this);
   585 	symbol->l_exp->accept(*this);
   557 	symbol->r_exp->accept(*this);
   586 	symbol->r_exp->accept(*this);
   558 	DO_BIN_OPER(bool,   <=);
   587 	DO_BINARY_OPER(bool,   <=);
   559 	DO_BIN_OPER(uint64, <=);
   588 	DO_BINARY_OPER(uint64, <=);
   560 	DO_BIN_OPER( int64, <=);
   589 	DO_BINARY_OPER( int64, <=);
   561 	DO_BIN_OPER(real64, <=);
   590 	DO_BINARY_OPER(real64, <=);
   562 	return NULL;
   591 	return NULL;
   563 }
   592 }
   564 
   593 
   565 
   594 
   566 void *constant_folding_c::visit(ge_expression_c *symbol) {
   595 void *constant_folding_c::visit(ge_expression_c *symbol) {
   567 	symbol->l_exp->accept(*this);
   596 	symbol->l_exp->accept(*this);
   568 	symbol->r_exp->accept(*this);
   597 	symbol->r_exp->accept(*this);
   569 	DO_BIN_OPER(bool,   >=);
   598 	DO_BINARY_OPER(bool,   >=);
   570 	DO_BIN_OPER(uint64, >=);
   599 	DO_BINARY_OPER(uint64, >=);
   571 	DO_BIN_OPER( int64, >=);
   600 	DO_BINARY_OPER( int64, >=);
   572 	DO_BIN_OPER(real64, >=);
   601 	DO_BINARY_OPER(real64, >=);
   573 	return NULL;
   602 	return NULL;
   574 }
   603 }
   575 
   604 
   576 
   605 
   577 void *constant_folding_c::visit(add_expression_c *symbol) {
   606 void *constant_folding_c::visit(add_expression_c *symbol) {
   578 	symbol->l_exp->accept(*this);
   607 	symbol->l_exp->accept(*this);
   579 	symbol->r_exp->accept(*this);
   608 	symbol->r_exp->accept(*this);
   580 	DO_BIN_OPER(uint64, +);   CHECK_OVERFLOW_uint64_SUM(symbol, symbol->l_exp, symbol->r_exp);
   609 	DO_BINARY_OPER(uint64, +);   CHECK_OVERFLOW_uint64_SUM(symbol, symbol->l_exp, symbol->r_exp);
   581 	DO_BIN_OPER( int64, +);   CHECK_OVERFLOW_int64_SUM (symbol, symbol->l_exp, symbol->r_exp);
   610 	DO_BINARY_OPER( int64, +);   CHECK_OVERFLOW_int64_SUM (symbol, symbol->l_exp, symbol->r_exp);
   582 	DO_BIN_OPER(real64, +);   CHECK_OVERFLOW_real64    (symbol);
   611 	DO_BINARY_OPER(real64, +);   CHECK_OVERFLOW_real64    (symbol);
   583 	return NULL;
   612 	return NULL;
   584 }
   613 }
   585 
   614 
   586 
   615 
   587 void *constant_folding_c::visit(sub_expression_c *symbol) {
   616 void *constant_folding_c::visit(sub_expression_c *symbol) {
   588 	symbol->l_exp->accept(*this);
   617 	symbol->l_exp->accept(*this);
   589 	symbol->r_exp->accept(*this);
   618 	symbol->r_exp->accept(*this);
   590 	DO_BIN_OPER(uint64, -);   CHECK_OVERFLOW_uint64_SUB(symbol, symbol->l_exp, symbol->r_exp);
   619 	DO_BINARY_OPER(uint64, -);   CHECK_OVERFLOW_uint64_SUB(symbol, symbol->l_exp, symbol->r_exp);
   591 	DO_BIN_OPER( int64, -);   CHECK_OVERFLOW_int64_SUB (symbol, symbol->l_exp, symbol->r_exp);
   620 	DO_BINARY_OPER( int64, -);   CHECK_OVERFLOW_int64_SUB (symbol, symbol->l_exp, symbol->r_exp);
   592 	DO_BIN_OPER(real64, -);   CHECK_OVERFLOW_real64    (symbol);
   621 	DO_BINARY_OPER(real64, -);   CHECK_OVERFLOW_real64    (symbol);
   593 	return NULL;
   622 	return NULL;
   594 }
   623 }
   595 
   624 
   596 
   625 
   597 void *constant_folding_c::visit(mul_expression_c *symbol) {
   626 void *constant_folding_c::visit(mul_expression_c *symbol) {
   598 	symbol->l_exp->accept(*this);
   627 	symbol->l_exp->accept(*this);
   599 	symbol->r_exp->accept(*this);
   628 	symbol->r_exp->accept(*this);
   600 	DO_BIN_OPER(uint64, *);   CHECK_OVERFLOW_uint64_MUL(symbol, symbol->l_exp, symbol->r_exp);
   629 	DO_BINARY_OPER(uint64, *);   CHECK_OVERFLOW_uint64_MUL(symbol, symbol->l_exp, symbol->r_exp);
   601 	DO_BIN_OPER( int64, *);   CHECK_OVERFLOW_int64_MUL (symbol, symbol->l_exp, symbol->r_exp);
   630 	DO_BINARY_OPER( int64, *);   CHECK_OVERFLOW_int64_MUL (symbol, symbol->l_exp, symbol->r_exp);
   602 	DO_BIN_OPER(real64, *);   CHECK_OVERFLOW_real64    (symbol);
   631 	DO_BINARY_OPER(real64, *);   CHECK_OVERFLOW_real64    (symbol);
   603 	return NULL;
   632 	return NULL;
   604 }
   633 }
   605 
   634 
   606 
   635 
   607 
   636 
   608 void *constant_folding_c::visit(div_expression_c *symbol) {
   637 void *constant_folding_c::visit(div_expression_c *symbol) {
   609 	symbol->l_exp->accept(*this);
   638 	symbol->l_exp->accept(*this);
   610 	symbol->r_exp->accept(*this);
   639 	symbol->r_exp->accept(*this);
   611 	if (ISZERO_CVALUE(uint64, symbol->r_exp))  {NEW_CVALUE(uint64, symbol); SET_OVFLOW(uint64, symbol);} else {DO_BIN_OPER(uint64, /); CHECK_OVERFLOW_uint64_DIV(symbol, symbol->l_exp, symbol->r_exp);};
   640 	if (ISZERO_CVALUE(uint64, symbol->r_exp))  {NEW_CVALUE(uint64, symbol); SET_OVFLOW(uint64, symbol);} else {DO_BINARY_OPER(uint64, /); CHECK_OVERFLOW_uint64_DIV(symbol, symbol->l_exp, symbol->r_exp);};
   612 	if (ISZERO_CVALUE( int64, symbol->r_exp))  {NEW_CVALUE( int64, symbol); SET_OVFLOW( int64, symbol);} else {DO_BIN_OPER( int64, /); CHECK_OVERFLOW_int64_DIV(symbol, symbol->l_exp, symbol->r_exp);};
   641 	if (ISZERO_CVALUE( int64, symbol->r_exp))  {NEW_CVALUE( int64, symbol); SET_OVFLOW( int64, symbol);} else {DO_BINARY_OPER( int64, /); CHECK_OVERFLOW_int64_DIV(symbol, symbol->l_exp, symbol->r_exp);};
   613 	if (ISZERO_CVALUE(real64, symbol->r_exp))  {NEW_CVALUE(real64, symbol); SET_OVFLOW(real64, symbol);} else {DO_BIN_OPER(real64, /); CHECK_OVERFLOW_real64(symbol);};
   642 	if (ISZERO_CVALUE(real64, symbol->r_exp))  {NEW_CVALUE(real64, symbol); SET_OVFLOW(real64, symbol);} else {DO_BINARY_OPER(real64, /); CHECK_OVERFLOW_real64(symbol);};
   614 	return NULL;
   643 	return NULL;
   615 }
   644 }
   616 
   645 
   617 
   646 
   618 void *constant_folding_c::visit(mod_expression_c *symbol) {
   647 void *constant_folding_c::visit(mod_expression_c *symbol) {
   622 	 *  IF (IN2 = 0) THEN OUT:=0 ; ELSE OUT:=IN1 - (IN1/IN2)*IN2 ; END_IF
   651 	 *  IF (IN2 = 0) THEN OUT:=0 ; ELSE OUT:=IN1 - (IN1/IN2)*IN2 ; END_IF
   623 	 *
   652 	 *
   624 	 * Note that, when IN1 = INT64_MIN, and IN2 = -1, an overflow occurs in the division,
   653 	 * Note that, when IN1 = INT64_MIN, and IN2 = -1, an overflow occurs in the division,
   625 	 * so although the MOD operation should be OK, acording to the above definition, we actually have an overflow!!
   654 	 * so although the MOD operation should be OK, acording to the above definition, we actually have an overflow!!
   626 	 */
   655 	 */
   627 	if (ISZERO_CVALUE(uint64, symbol->r_exp))  {NEW_CVALUE(uint64, symbol); SET_CVALUE(uint64, symbol, 0);} else {DO_BIN_OPER(uint64, %); CHECK_OVERFLOW_uint64_MOD(symbol, symbol->l_exp, symbol->r_exp);};
   656 	if (ISZERO_CVALUE(uint64, symbol->r_exp))  {NEW_CVALUE(uint64, symbol); SET_CVALUE(uint64, symbol, 0);} else {DO_BINARY_OPER(uint64, %); CHECK_OVERFLOW_uint64_MOD(symbol, symbol->l_exp, symbol->r_exp);};
   628 	if (ISZERO_CVALUE( int64, symbol->r_exp))  {NEW_CVALUE( int64, symbol); SET_CVALUE( int64, symbol, 0);} else {DO_BIN_OPER( int64, %); CHECK_OVERFLOW_int64_MOD(symbol, symbol->l_exp, symbol->r_exp);};
   657 	if (ISZERO_CVALUE( int64, symbol->r_exp))  {NEW_CVALUE( int64, symbol); SET_CVALUE( int64, symbol, 0);} else {DO_BINARY_OPER( int64, %); CHECK_OVERFLOW_int64_MOD(symbol, symbol->l_exp, symbol->r_exp);};
   629 	return NULL;
   658 	return NULL;
   630 }
   659 }
   631 
   660 
   632 
   661 
   633 void *constant_folding_c::visit(power_expression_c *symbol) {
   662 void *constant_folding_c::visit(power_expression_c *symbol) {