stage3/constant_folding.cc
changeset 572 c353bc67bf91
parent 570 cb704eca7e37
child 573 e28b47911c19
equal deleted inserted replaced
571:97b85630e496 572:c353bc67bf91
    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 
       
    39 
       
    40 
    34 /* Do constant folding...
    41 /* Do constant folding...
    35  *
    42  *
    36  * I.e., Determine the value of all expressions in which only constant values (i.e. literals) are used.
    43  * I.e., Determine the value of all expressions in which only constant values (i.e. literals) are used.
    37  * The (constant) result of each operation is stored (annotated) in the respective operation symbol 
    44  * The (constant) result of each operation is stored (annotated) in the respective operation symbol 
    38  * (e.g.: add_expression_c) in the abstract syntax tree,
    45  * (e.g.: add_expression_c) in the abstract syntax tree,
    41  *       2 + 3         -> the constant value '5'    is stored in the add_expression_c symbol.
    48  *       2 + 3         -> the constant value '5'    is stored in the add_expression_c symbol.
    42  *       22.2 - 5.0    -> the constant value '17.2' is stored in the add_expression_c symbol.
    49  *       22.2 - 5.0    -> the constant value '17.2' is stored in the add_expression_c symbol.
    43  *       etc...
    50  *       etc...
    44  *
    51  *
    45  *
    52  *
    46  * NOTE 1 that some operations and constants can have multiple data types. For example,
    53  * NOTE 1 
       
    54  *      Some operations and constants can have multiple data types. For example,
    47  *        1 AND 0
    55  *        1 AND 0
    48  *      may be either a BOOL, BYTE, WORD or LWORD.
    56  *      may be either a BOOL, BYTE, WORD or LWORD.
    49  *
    57  *
    50  *      The same happens with 
    58  *      The same happens with 
    51  *        1 + 2
    59  *        1 + 2
   107  *    it may happen that some of them overflow, while other do not.
   115  *    it may happen that some of them overflow, while other do not.
   108  *    We must wait for data type checking to determine the exact data type of each expression
   116  *    We must wait for data type checking to determine the exact data type of each expression
   109  *    before we can decide whether or not we should print out an overflow error message.
   117  *    before we can decide whether or not we should print out an overflow error message.
   110  *
   118  *
   111  *    For this reason, this visitor merely annotates the abstract syntax tree, and leaves the
   119  *    For this reason, this visitor merely annotates the abstract syntax tree, and leaves the
   112  `    actuall printing of errors for the print_datatype_errors_c class!
   120  *    actuall printing of errors for the print_datatype_errors_c class!
   113  */
   121  */
   114 
   122 
   115 #include "constant_folding.hh"
   123 #include "constant_folding.hh"
   116 #include <typeinfo>
       
   117 #include <limits>
   124 #include <limits>
       
   125 #include <stdint.h> /* required for UINT64_MAX, INT64_MAX, INT64_MIN, ... */
   118 #include <math.h> /* required for pow function */
   126 #include <math.h> /* required for pow function */
   119 #include <stdlib.h> /* required for malloc() */
   127 #include <stdlib.h> /* required for malloc() */
   120 
   128 
   121 
   129 #if 1
       
   130 #define INT64_MAX (std::numeric_limits< int64_t >::max())
       
   131 #define INT64_MIN (std::numeric_limits< int64_t >::min()) 
       
   132 #else
       
   133 /* An alternative is to use the std::numeric_limits< uint64_t >::min() / max()  methods already defined in #include <limits> */
       
   134 #define __STDC_LIMIT_MACROS /* required for UINT64_MAX, INT64_MAX, INT64_MIN, ... */
       
   135 #include <stdint.h>         /* required for UINT64_MAX, INT64_MAX, INT64_MIN, ... */
       
   136 #endif
   122 
   137 
   123 
   138 
   124 #define FIRST_(symbol1, symbol2) (((symbol1)->first_order < (symbol2)->first_order)   ? (symbol1) : (symbol2))
   139 #define FIRST_(symbol1, symbol2) (((symbol1)->first_order < (symbol2)->first_order)   ? (symbol1) : (symbol2))
   125 #define  LAST_(symbol1, symbol2) (((symbol1)->last_order  > (symbol2)->last_order)    ? (symbol1) : (symbol2))
   140 #define  LAST_(symbol1, symbol2) (((symbol1)->last_order  > (symbol2)->last_order)    ? (symbol1) : (symbol2))
   126 
   141 
   170 #define DO_BIN_OPER(dtype, oper)\
   185 #define DO_BIN_OPER(dtype, oper)\
   171 	if (VALID_CVALUE(dtype, symbol->r_exp) && VALID_CVALUE(dtype, symbol->l_exp)) {                                \
   186 	if (VALID_CVALUE(dtype, symbol->r_exp) && VALID_CVALUE(dtype, symbol->l_exp)) {                                \
   172 		NEW_CVALUE(dtype, symbol);                                                                             \
   187 		NEW_CVALUE(dtype, symbol);                                                                             \
   173 		SET_CVALUE(dtype, symbol, GET_CVALUE(dtype, symbol->l_exp) oper GET_CVALUE(dtype, symbol->r_exp));     \
   188 		SET_CVALUE(dtype, symbol, GET_CVALUE(dtype, symbol->l_exp) oper GET_CVALUE(dtype, symbol->r_exp));     \
   174 	}
   189 	}
       
   190 
       
   191 
       
   192 
       
   193 
       
   194 
       
   195 
       
   196 
       
   197 
       
   198 
       
   199 
       
   200 
       
   201 /* res = a + b */
       
   202 static void CHECK_OVERFLOW_uint64_SUM(symbol_c *res, symbol_c *a, symbol_c *b) {
       
   203 	if (VALID_CVALUE(uint64, res))
       
   204 		/* If sum is smaller than either operand => overflow! */
       
   205 		if (GET_CVALUE(uint64, res) < GET_CVALUE(uint64, a))
       
   206 			SET_OVFLOW(uint64, res);
       
   207 }
       
   208 
       
   209 /* res = a - b */
       
   210 static void CHECK_OVERFLOW_uint64_SUB(symbol_c *res, symbol_c *a, symbol_c *b) {
       
   211 	if (VALID_CVALUE(uint64, res))
       
   212 		/* If diference is larger than a => overflow! */
       
   213 		if (GET_CVALUE(uint64, res) > GET_CVALUE(uint64, a))
       
   214 			SET_OVFLOW(uint64, res);
       
   215 }
       
   216 
       
   217 /* res = a * b */
       
   218 static void CHECK_OVERFLOW_uint64_MUL(symbol_c *res, symbol_c *a, symbol_c *b) {
       
   219 	if (VALID_CVALUE(uint64, res))
       
   220 		if (false /* TODO */)
       
   221 			SET_OVFLOW(uint64, res);
       
   222 }
       
   223 
       
   224 /* res = a / b */
       
   225 static void CHECK_OVERFLOW_uint64_DIV(symbol_c *res, symbol_c *a, symbol_c *b) {
       
   226 	if (VALID_CVALUE(uint64, res))
       
   227 		if (false /* TODO */)
       
   228 			SET_OVFLOW(uint64, res);
       
   229 }
       
   230 
       
   231 /* res = a MOD b */
       
   232 static void CHECK_OVERFLOW_uint64_MOD(symbol_c *res, symbol_c *a, symbol_c *b) {
       
   233 	if (VALID_CVALUE(uint64, res))
       
   234 		if (false /* TODO */)
       
   235 			SET_OVFLOW(uint64, res);
       
   236 }
       
   237 
       
   238 /* res = a + b */
       
   239 static void CHECK_OVERFLOW_int64_SUM(symbol_c *res, symbol_c *a_ptr, symbol_c *b_ptr) {
       
   240 	int64_t a = GET_CVALUE(int64, a_ptr);
       
   241 	int64_t b = GET_CVALUE(int64, b_ptr);
       
   242 	if (VALID_CVALUE(int64, res))
       
   243 		/* The following test is valid no matter what representation is being used (e.g. two's complement, etc...) */
       
   244 		if (((b > 0) && (a > (INT64_MAX - b)))
       
   245 		 || ((b < 0) && (a < (INT64_MIN - b))))
       
   246 			SET_OVFLOW(int64, res);
       
   247 }
       
   248 
       
   249 /* res = a - b */
       
   250 static void CHECK_OVERFLOW_int64_SUB(symbol_c *res, symbol_c *a_ptr, symbol_c *b_ptr) {
       
   251 	int64_t a = GET_CVALUE(int64, a_ptr);
       
   252 	int64_t b = GET_CVALUE(int64, b_ptr);
       
   253 	if (VALID_CVALUE(int64, res))
       
   254 		/* The following test is valid no matter what representation is being used (e.g. two's complement, etc...) */
       
   255 		if (((b > 0) && (a < (INT64_MIN + b)))
       
   256 		 || ((b < 0) && (a > (INT64_MAX + b))))
       
   257 			SET_OVFLOW(int64, res);
       
   258 }
       
   259 
       
   260 
       
   261 /* res = a * b */
       
   262 static void CHECK_OVERFLOW_int64_MUL(symbol_c *res, symbol_c *a_ptr, symbol_c *b_ptr) {
       
   263 	int64_t a = GET_CVALUE(int64, a_ptr);
       
   264 	int64_t b = GET_CVALUE(int64, b_ptr);
       
   265 	if (VALID_CVALUE(int64, res))
       
   266 		if (   ( (a > 0) &&  (b > 0) &&             (a > (INT64_MAX / b))) 
       
   267 		    || ( (a > 0) && !(b > 0) &&             (b < (INT64_MIN / a))) 
       
   268 		    || (!(a > 0) &&  (b > 0) &&             (a < (INT64_MIN / b))) 
       
   269 		    || (!(a > 0) && !(b > 0) && (a != 0) && (b < (INT64_MAX / a))))
       
   270 			SET_OVFLOW(int64, res);
       
   271 }
       
   272 
       
   273 
       
   274 /* res = a / b */
       
   275 static void CHECK_OVERFLOW_int64_DIV(symbol_c *res, symbol_c *a_ptr, symbol_c *b_ptr) {
       
   276 	int64_t a = GET_CVALUE(int64, a_ptr);
       
   277 	int64_t b = GET_CVALUE(int64, b_ptr);
       
   278 	if (VALID_CVALUE(int64, res))
       
   279 		if ((b == 0) || ((a == INT64_MIN) && (b == -1)))
       
   280 			SET_OVFLOW(int64, res);
       
   281 }
       
   282 
       
   283 
       
   284 /* res = a MOD b */
       
   285 static void CHECK_OVERFLOW_int64_MOD(symbol_c *res, symbol_c *a_ptr, symbol_c *b_ptr) {
       
   286 	int64_t a = GET_CVALUE(int64, a_ptr);
       
   287 	int64_t b = GET_CVALUE(int64, b_ptr);
       
   288 	/* IEC 61131-3 standard says IN1 MOD IN2 must be equivalent to
       
   289 	 *  IF (IN2 = 0) THEN OUT:=0 ; ELSE OUT:=IN1 - (IN1/IN2)*IN2 ; END_IF
       
   290 	 *
       
   291 	 * Note that, when IN1 = INT64_MIN, and IN2 = -1, an overflow occurs in the division,
       
   292 	 * so although the MOD operation should be OK, acording to the above definition, we actually have an overflow!!
       
   293 	 *
       
   294 	 * On the other hand, division by 0 is OK!!
       
   295 	 */
       
   296 	if (VALID_CVALUE(int64, res))
       
   297 		if ((a == INT64_MIN) && (b == -1))
       
   298 			SET_OVFLOW(int64, res);
       
   299 }
       
   300 
       
   301 
       
   302 /* res = - a */
       
   303 static void CHECK_OVERFLOW_int64_NEG(symbol_c *res, symbol_c *a_ptr) {
       
   304 	int64_t a = GET_CVALUE(int64, a_ptr);
       
   305 	if (VALID_CVALUE(int64, res))
       
   306 		if (a == INT64_MIN)
       
   307 			SET_OVFLOW(int64, res);
       
   308 }
       
   309 
       
   310 
       
   311 
       
   312 static void CHECK_OVERFLOW_real64(symbol_c *res) {
       
   313 	if (VALID_CVALUE(real64, res))
       
   314         	/* NaN => underflow, overflow, number is a higher precision format, is a complex number (IEEE standard) */
       
   315 		 if (isnan(GET_CVALUE(real64, res)))
       
   316 			SET_OVFLOW(real64, res);
       
   317 }
       
   318 
       
   319 
       
   320 
       
   321 
       
   322 
       
   323 
       
   324 
       
   325 
       
   326 
   175 
   327 
   176 
   328 
   177 
   329 
   178 
   330 
   179 
   331 
   226 	symbol->exp->accept(*this);
   378 	symbol->exp->accept(*this);
   227 	if (!VALID_CVALUE(real64, symbol->exp))
   379 	if (!VALID_CVALUE(real64, symbol->exp))
   228 		return NULL;
   380 		return NULL;
   229 	NEW_CVALUE(real64, symbol);
   381 	NEW_CVALUE(real64, symbol);
   230 	SET_CVALUE(real64, symbol, - GET_CVALUE( real64, symbol->exp));
   382 	SET_CVALUE(real64, symbol, - GET_CVALUE( real64, symbol->exp));
       
   383 	CHECK_OVERFLOW_real64(symbol);
   231 	return NULL;
   384 	return NULL;
   232 }
   385 }
   233 
   386 
   234 /* | '-' integer	{$$ = new neg_integer_c($2, locloc(@$));} */
   387 /* | '-' integer	{$$ = new neg_integer_c($2, locloc(@$));} */
   235 void *constant_folding_c::visit(neg_integer_c *symbol) {
   388 void *constant_folding_c::visit(neg_integer_c *symbol) {
   236 	symbol->exp->accept(*this);
   389 	symbol->exp->accept(*this);
   237 	if (VALID_CVALUE(int64, symbol->exp)) {
   390 	if (VALID_CVALUE(int64, symbol->exp)) {
   238 		NEW_CVALUE( int64, symbol);
   391 		NEW_CVALUE( int64, symbol);
   239 		SET_CVALUE( int64, symbol, - GET_CVALUE( int64, symbol->exp));
   392 		SET_CVALUE( int64, symbol, - GET_CVALUE( int64, symbol->exp));
   240 	}
   393 	}
   241         /* TODO: check for overflows */
   394        	CHECK_OVERFLOW_int64_NEG(symbol, symbol->exp);
   242 	return NULL;
   395 	return NULL;
   243 }
   396 }
   244 
   397 
   245 
   398 
   246 void *constant_folding_c::visit(binary_integer_c *symbol) {
   399 void *constant_folding_c::visit(binary_integer_c *symbol) {
   420 	DO_BIN_OPER(real64, >=);
   573 	DO_BIN_OPER(real64, >=);
   421 	return NULL;
   574 	return NULL;
   422 }
   575 }
   423 
   576 
   424 
   577 
   425 #define CHECK_OVERFLOW_SUM(dtype)\
       
   426 	if (VALID_CVALUE(dtype, symbol))                                                                                                             \
       
   427 		if ((((std::numeric_limits< dtype##_t >::max() - GET_CVALUE(dtype, symbol->l_exp)) < (GET_CVALUE(dtype, symbol->r_exp))) ? 1 : 0) || \
       
   428 		    (((std::numeric_limits< dtype##_t >::min() + GET_CVALUE(dtype, symbol->l_exp)) > (GET_CVALUE(dtype, symbol->r_exp))) ? 1 : 0))   \
       
   429 			SET_OVFLOW(dtype, symbol);
       
   430 #define CHECK_OVERFLOW_real64  \
       
   431 	if (VALID_CVALUE(real64, symbol))                                                                                                            \
       
   432         	/* NaN => underflow, overflow, number is a higher precision format, is a complex number (IEEE standard) */                           \
       
   433 		 if (isnan(GET_CVALUE(real64, symbol)))                                                                                              \
       
   434 			SET_OVFLOW(real64, symbol);
       
   435 void *constant_folding_c::visit(add_expression_c *symbol) {
   578 void *constant_folding_c::visit(add_expression_c *symbol) {
   436 	symbol->l_exp->accept(*this);
   579 	symbol->l_exp->accept(*this);
   437 	symbol->r_exp->accept(*this);
   580 	symbol->r_exp->accept(*this);
   438 	DO_BIN_OPER(uint64, +);   CHECK_OVERFLOW_SUM(uint64);
   581 	DO_BIN_OPER(uint64, +);   CHECK_OVERFLOW_uint64_SUM(symbol, symbol->l_exp, symbol->r_exp);
   439 	DO_BIN_OPER( int64, +);   CHECK_OVERFLOW_SUM( int64);
   582 	DO_BIN_OPER( int64, +);   CHECK_OVERFLOW_int64_SUM (symbol, symbol->l_exp, symbol->r_exp);
   440 	DO_BIN_OPER(real64, +);   CHECK_OVERFLOW_real64;
   583 	DO_BIN_OPER(real64, +);   CHECK_OVERFLOW_real64    (symbol);
   441 	return NULL;
   584 	return NULL;
   442 }
   585 }
   443 
   586 
   444 
   587 
   445 #define CHECK_OVERFLOW_SUB(dtype)\
       
   446 	if (VALID_CVALUE(dtype, symbol))                                                                                                             \
       
   447 		if ((((std::numeric_limits< dtype##_t >::max() - GET_CVALUE(dtype, symbol->l_exp)) < (-GET_CVALUE(dtype, symbol->r_exp))) ? 1 : 0) || \
       
   448 		    (((std::numeric_limits< dtype##_t >::min() + GET_CVALUE(dtype, symbol->l_exp)) > (-GET_CVALUE(dtype, symbol->r_exp))) ? 1 : 0))   \
       
   449 			SET_OVFLOW(dtype, symbol);
       
   450 void *constant_folding_c::visit(sub_expression_c *symbol) {
   588 void *constant_folding_c::visit(sub_expression_c *symbol) {
   451 	symbol->l_exp->accept(*this);
   589 	symbol->l_exp->accept(*this);
   452 	symbol->r_exp->accept(*this);
   590 	symbol->r_exp->accept(*this);
   453 	DO_BIN_OPER(uint64, -);   CHECK_OVERFLOW_SUB(uint64);
   591 	DO_BIN_OPER(uint64, -);   CHECK_OVERFLOW_uint64_SUB(symbol, symbol->l_exp, symbol->r_exp);
   454 	DO_BIN_OPER( int64, -);   CHECK_OVERFLOW_SUB( int64);
   592 	DO_BIN_OPER( int64, -);   CHECK_OVERFLOW_int64_SUB (symbol, symbol->l_exp, symbol->r_exp);
   455 	DO_BIN_OPER(real64, -);   CHECK_OVERFLOW_real64;
   593 	DO_BIN_OPER(real64, -);   CHECK_OVERFLOW_real64    (symbol);
   456 	return NULL;
   594 	return NULL;
   457 }
   595 }
   458 
   596 
   459 
   597 
   460 /* TODO!!! */
       
   461 #define CHECK_OVERFLOW_MUL(dtype)\
       
   462 	if (VALID_CVALUE(dtype, symbol))                                                                                                             \
       
   463 		if (false)                                                                                                                                   \
       
   464 			SET_OVFLOW(dtype, symbol);
       
   465 void *constant_folding_c::visit(mul_expression_c *symbol) {
   598 void *constant_folding_c::visit(mul_expression_c *symbol) {
   466 	symbol->l_exp->accept(*this);
   599 	symbol->l_exp->accept(*this);
   467 	symbol->r_exp->accept(*this);
   600 	symbol->r_exp->accept(*this);
   468 	DO_BIN_OPER(uint64, *);  CHECK_OVERFLOW_MUL(uint64);
   601 	DO_BIN_OPER(uint64, *);   CHECK_OVERFLOW_uint64_MUL(symbol, symbol->l_exp, symbol->r_exp);
   469 	DO_BIN_OPER( int64, *);  CHECK_OVERFLOW_MUL( int64);
   602 	DO_BIN_OPER( int64, *);   CHECK_OVERFLOW_int64_MUL (symbol, symbol->l_exp, symbol->r_exp);
   470 	DO_BIN_OPER(real64, *);  CHECK_OVERFLOW_real64;
   603 	DO_BIN_OPER(real64, *);   CHECK_OVERFLOW_real64    (symbol);
   471 	return NULL;
   604 	return NULL;
   472 }
   605 }
   473 
   606 
   474 
   607 
   475 
   608 
   476 /* TODO!!! */
       
   477 #define CHECK_OVERFLOW_DIV(dtype)\
       
   478 	if (VALID_CVALUE(dtype, symbol))                                                                                                             \
       
   479 		if (false)                                                                                                                                   \
       
   480 			SET_OVFLOW(dtype, symbol);
       
   481 void *constant_folding_c::visit(div_expression_c *symbol) {
   609 void *constant_folding_c::visit(div_expression_c *symbol) {
   482 	symbol->l_exp->accept(*this);
   610 	symbol->l_exp->accept(*this);
   483 	symbol->r_exp->accept(*this);
   611 	symbol->r_exp->accept(*this);
   484 	if (ISZERO_CVALUE(uint64, symbol->r_exp))  {NEW_CVALUE(uint64, symbol); SET_OVFLOW(uint64, symbol);} else {DO_BIN_OPER(uint64, /); CHECK_OVERFLOW_DIV(uint64)};
   612 	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);};
   485 	if (ISZERO_CVALUE( int64, symbol->r_exp))  {NEW_CVALUE( int64, symbol); SET_OVFLOW( int64, symbol);} else {DO_BIN_OPER( int64, /); CHECK_OVERFLOW_DIV( int64)};
   613 	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);};
   486 	if (ISZERO_CVALUE(real64, symbol->r_exp))  {NEW_CVALUE(real64, symbol); SET_OVFLOW(real64, symbol);} else {DO_BIN_OPER(real64, /); CHECK_OVERFLOW_real64;};
   614 	if (ISZERO_CVALUE(real64, symbol->r_exp))  {NEW_CVALUE(real64, symbol); SET_OVFLOW(real64, symbol);} else {DO_BIN_OPER(real64, /); CHECK_OVERFLOW_real64(symbol);};
   487 	return NULL;
   615 	return NULL;
   488 }
   616 }
   489 
   617 
   490 
   618 
   491 /* TODO!!! */
       
   492 #define CHECK_OVERFLOW_MOD(dtype)\
       
   493 	if (VALID_CVALUE(dtype, symbol))                                                                                                             \
       
   494 		if (false)                                                                                                                                   \
       
   495 			SET_OVFLOW(dtype, symbol);
       
   496 void *constant_folding_c::visit(mod_expression_c *symbol) {
   619 void *constant_folding_c::visit(mod_expression_c *symbol) {
   497 	symbol->l_exp->accept(*this);
   620 	symbol->l_exp->accept(*this);
   498 	symbol->r_exp->accept(*this);
   621 	symbol->r_exp->accept(*this);
   499 	if (ISZERO_CVALUE(uint64, symbol->r_exp))  {NEW_CVALUE(uint64, symbol); SET_OVFLOW(uint64, symbol);} else {DO_BIN_OPER(uint64, %); CHECK_OVERFLOW_MOD(uint64)};
   622 	/* IEC 61131-3 standard says IN1 MOD IN2 must be equivalent to
   500 	if (ISZERO_CVALUE( int64, symbol->r_exp))  {NEW_CVALUE( int64, symbol); SET_OVFLOW( int64, symbol);} else {DO_BIN_OPER( int64, %); CHECK_OVERFLOW_MOD( int64)};
   623 	 *  IF (IN2 = 0) THEN OUT:=0 ; ELSE OUT:=IN1 - (IN1/IN2)*IN2 ; END_IF
       
   624 	 *
       
   625 	 * Note that, when IN1 = INT64_MIN, and IN2 = -1, an overflow occurs in the division,
       
   626 	 * so although the MOD operation should be OK, acording to the above definition, we actually have an overflow!!
       
   627 	 */
       
   628 	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);};
       
   629 	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);};
   501 	return NULL;
   630 	return NULL;
   502 }
   631 }
   503 
   632 
   504 
   633 
   505 void *constant_folding_c::visit(power_expression_c *symbol) {
   634 void *constant_folding_c::visit(power_expression_c *symbol) {
   515 	}
   644 	}
   516 	if (VALID_CVALUE(real64, symbol->l_exp) && VALID_CVALUE(uint64, symbol->r_exp)) {
   645 	if (VALID_CVALUE(real64, symbol->l_exp) && VALID_CVALUE(uint64, symbol->r_exp)) {
   517 		NEW_CVALUE(real64, symbol);
   646 		NEW_CVALUE(real64, symbol);
   518 		SET_CVALUE(real64, symbol, pow(GET_CVALUE(real64, symbol->l_exp), GET_CVALUE(uint64, symbol->r_exp)));
   647 		SET_CVALUE(real64, symbol, pow(GET_CVALUE(real64, symbol->l_exp), GET_CVALUE(uint64, symbol->r_exp)));
   519 	}
   648 	}
   520 	CHECK_OVERFLOW_real64;
   649 	CHECK_OVERFLOW_real64(symbol);
   521 	return NULL;
   650 	return NULL;
   522 }
   651 }
   523 
   652 
   524 
   653 
   525 /* TODO!!! */
       
   526 #define CHECK_OVERFLOW_NEG(dtype)\
       
   527 	if (VALID_CVALUE(dtype, symbol))                                                                                                             \
       
   528 		if (false)                                                                                                                                   \
       
   529 			SET_OVFLOW(dtype, symbol);
       
   530 void *constant_folding_c::visit(neg_expression_c *symbol) {
   654 void *constant_folding_c::visit(neg_expression_c *symbol) {
   531 	symbol->exp->accept(*this);
   655 	symbol->exp->accept(*this);
   532 	if (VALID_CVALUE( int64, symbol->exp)) {
   656 	if (VALID_CVALUE( int64, symbol->exp)) {
   533 		NEW_CVALUE( int64, symbol);
   657 		NEW_CVALUE( int64, symbol);
   534 		SET_CVALUE( int64, symbol, - GET_CVALUE( int64, symbol->exp));
   658 		SET_CVALUE( int64, symbol, - GET_CVALUE( int64, symbol->exp));
   535 	}
   659 	}
   536 	if (VALID_CVALUE(real64, symbol->exp)) {
   660 	if (VALID_CVALUE(real64, symbol->exp)) {
   537 		NEW_CVALUE(real64, symbol);
   661 		NEW_CVALUE(real64, symbol);
   538 		SET_CVALUE(real64, symbol, - GET_CVALUE(real64, symbol->exp));
   662 		SET_CVALUE(real64, symbol, - GET_CVALUE(real64, symbol->exp));
   539 	}
   663 	}
   540 	CHECK_OVERFLOW_NEG( int64);
   664 	CHECK_OVERFLOW_int64_NEG(symbol, symbol->exp);
   541 	CHECK_OVERFLOW_real64;
   665 	CHECK_OVERFLOW_real64(symbol);
   542 	return NULL;
   666 	return NULL;
   543 }
   667 }
   544 
   668 
   545 
   669 
   546 
   670