stage3/constant_folding.cc
changeset 643 1cc0e1ca2aad
parent 640 ffa02cf2b335
child 648 5ca2aabb8bcb
equal deleted inserted replaced
641:5681f600ac18 643:1cc0e1ca2aad
   173 
   173 
   174 
   174 
   175 
   175 
   176 
   176 
   177 
   177 
   178 #define SET_CVALUE(dtype, symbol, new_value)  ((symbol)->const_value._##dtype.value) = new_value; ((symbol)->const_value._##dtype.status) = symbol_c::cs_const_value;
   178 #define SET_CVALUE(dtype, symbol, new_value) {((symbol)->const_value._##dtype.value) = new_value; ((symbol)->const_value._##dtype.status) = symbol_c::cs_const_value;}
   179 #define GET_CVALUE(dtype, symbol)             ((symbol)->const_value._##dtype.value)
   179 #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
   180 #define SET_OVFLOW(dtype, symbol)             ((symbol)->const_value._##dtype.status) = symbol_c::cs_overflow
   181 #define SET_NONCONST(dtype, symbol)           ((symbol)->const_value._##dtype.status) = symbol_c::cs_non_const
   181 #define SET_NONCONST(dtype, symbol)           ((symbol)->const_value._##dtype.status) = symbol_c::cs_non_const
   182 
   182 
   183 #define VALID_CVALUE(dtype, symbol)           (symbol_c::cs_const_value == (symbol)->const_value._##dtype.status)
   183 #define VALID_CVALUE(dtype, symbol)           (symbol_c::cs_const_value == (symbol)->const_value._##dtype.status)
       
   184 #define IS_OVFLOW(dtype, symbol)              (symbol_c::cs_overflow    == (symbol)->const_value._##dtype.status)
   184 #define ISZERO_CVALUE(dtype, symbol)          ((VALID_CVALUE(dtype, symbol)) && (GET_CVALUE(dtype, symbol) == 0))
   185 #define ISZERO_CVALUE(dtype, symbol)          ((VALID_CVALUE(dtype, symbol)) && (GET_CVALUE(dtype, symbol) == 0))
   185 
   186 
   186 #define ISEQUAL_CVALUE(dtype, symbol1, symbol2) \
   187 #define ISEQUAL_CVALUE(dtype, symbol1, symbol2) \
   187 	(VALID_CVALUE(dtype, symbol1) && VALID_CVALUE(dtype, symbol2) && (GET_CVALUE(dtype, symbol1) == GET_CVALUE(dtype, symbol2))) 
   188 	(VALID_CVALUE(dtype, symbol1) && VALID_CVALUE(dtype, symbol2) && (GET_CVALUE(dtype, symbol1) == GET_CVALUE(dtype, symbol2))) 
   188 
   189 
   189 #define DO_BINARY_OPER(dtype, oper, otype)\
   190 #define DO_BINARY_OPER(oper_type, operation, res_type, operand1, operand2) {                                             \
   190 	if (VALID_CVALUE(dtype, symbol->r_exp) && VALID_CVALUE(dtype, symbol->l_exp)) {                                \
   191 	if (VALID_CVALUE(oper_type, operand1) && VALID_CVALUE(oper_type, operand2))                                       \
   191 		SET_CVALUE(otype, symbol, GET_CVALUE(dtype, symbol->l_exp) oper GET_CVALUE(dtype, symbol->r_exp));     \
       
   192 	}
       
   193 
       
   194 #define DO_BINARY_OPER_(oper_type, operation, res_type, operand1, operand2)\
       
   195 	if (VALID_CVALUE(oper_type, operand1) && VALID_CVALUE(oper_type, operand2)) {                                     \
       
   196 		SET_CVALUE(res_type, symbol, GET_CVALUE(oper_type, operand1) operation GET_CVALUE(oper_type, operand2));  \
   192 		SET_CVALUE(res_type, symbol, GET_CVALUE(oper_type, operand1) operation GET_CVALUE(oper_type, operand2));  \
   197 	}
   193 }
   198 
   194 
   199 #define DO_UNARY_OPER(dtype, operation, operand)\
   195 #define DO_UNARY_OPER(dtype, operation, operand) {                                                                        \
   200 	if (VALID_CVALUE(dtype, operand)) {                                                                               \
   196 	if (VALID_CVALUE(dtype, operand))                                                                                 \
   201 		SET_CVALUE(dtype, symbol, operation GET_CVALUE(dtype, operand));                                          \
   197 		SET_CVALUE(dtype, symbol, operation GET_CVALUE(dtype, operand));                                          \
   202 	}
   198 }
   203 
   199 
   204 
   200 
   205 
   201 
   206 
   202 
   207 
   203 
   428 	if (false) 
   424 	if (false) 
   429 		SET_OVFLOW(uint64, res);
   425 		SET_OVFLOW(uint64, res);
   430 }
   426 }
   431 
   427 
   432 
   428 
       
   429 /* res = - a */
       
   430 static void CHECK_OVERFLOW_uint64_NEG(symbol_c *res, symbol_c *a) {
       
   431 	/* The only legal operation is res = -0, everything else is an overflow! */
       
   432 	if (VALID_CVALUE(uint64, a) && (GET_CVALUE(uint64, a) != 0))
       
   433 		SET_OVFLOW(uint64, res);
       
   434 }
       
   435 
       
   436 
       
   437 
       
   438 
       
   439 
       
   440 
   433 /* res = a + b */
   441 /* res = a + b */
   434 static void CHECK_OVERFLOW_int64_SUM(symbol_c *res, symbol_c *a_ptr, symbol_c *b_ptr) {
   442 static void CHECK_OVERFLOW_int64_SUM(symbol_c *res, symbol_c *a_ptr, symbol_c *b_ptr) {
   435 	if (!VALID_CVALUE(int64, res))
   443 	if (!VALID_CVALUE(int64, res))
   436 		return;
   444 		return;
   437 	int64_t a = GET_CVALUE(int64, a_ptr);
   445 	int64_t a = GET_CVALUE(int64, a_ptr);
   499 		SET_OVFLOW(int64, res);
   507 		SET_OVFLOW(int64, res);
   500 }
   508 }
   501 
   509 
   502 
   510 
   503 /* res = - a */
   511 /* res = - a */
   504 static void CHECK_OVERFLOW_int64_NEG(symbol_c *res, symbol_c *a_ptr) {
   512 static void CHECK_OVERFLOW_int64_NEG(symbol_c *res, symbol_c *a) {
   505 	if (!VALID_CVALUE(int64, res))
   513 	if (!VALID_CVALUE(int64, res))
   506 		return;
   514 		return;
   507 	int64_t a = GET_CVALUE(int64, a_ptr);
   515 	if (GET_CVALUE(int64, a) == INT64_MIN)
   508 	if (a == INT64_MIN)
       
   509 		SET_OVFLOW(int64, res);
   516 		SET_OVFLOW(int64, res);
   510 }
   517 }
       
   518 
   511 
   519 
   512 
   520 
   513 
   521 
   514 static void CHECK_OVERFLOW_real64(symbol_c *res_ptr) {
   522 static void CHECK_OVERFLOW_real64(symbol_c *res_ptr) {
   515 	if (!VALID_CVALUE(real64, res_ptr))
   523 	if (!VALID_CVALUE(real64, res_ptr))
   537 /***********************************************************************/
   545 /***********************************************************************/
   538 
   546 
   539 /* static void *handle_cmp(symbol_c *symbol, symbol_c *oper1, symbol_c *oper2, OPERATION) */
   547 /* static void *handle_cmp(symbol_c *symbol, symbol_c *oper1, symbol_c *oper2, OPERATION) */
   540 #define handle_cmp(symbol, oper1, oper2, operation) {               \
   548 #define handle_cmp(symbol, oper1, oper2, operation) {               \
   541 	if ((NULL == oper1) || (NULL == oper2)) return NULL;        \
   549 	if ((NULL == oper1) || (NULL == oper2)) return NULL;        \
   542 	DO_BINARY_OPER_(  bool, operation, bool, oper1, oper2);     \
   550 	DO_BINARY_OPER(  bool, operation, bool, oper1, oper2);     \
   543 	DO_BINARY_OPER_(uint64, operation, bool, oper1, oper2);     \
   551 	DO_BINARY_OPER(uint64, operation, bool, oper1, oper2);     \
   544 	DO_BINARY_OPER_( int64, operation, bool, oper1, oper2);     \
   552 	DO_BINARY_OPER( int64, operation, bool, oper1, oper2);     \
   545 	DO_BINARY_OPER_(real64, operation, bool, oper1, oper2);     \
   553 	DO_BINARY_OPER(real64, operation, bool, oper1, oper2);     \
   546 	return NULL;                                                \
   554 	return NULL;                                                \
   547 }
   555 }
   548 
   556 
   549 
   557 
   550 /* NOTE: the MOVE standard function is equivalent to the ':=' in ST syntax */
   558 /* NOTE: the MOVE standard function is equivalent to the ':=' in ST syntax */
   555 }
   563 }
   556 
   564 
   557 
   565 
   558 /* unary negation (multiply by -1) */
   566 /* unary negation (multiply by -1) */
   559 static void *handle_neg(symbol_c *symbol, symbol_c *oper) {
   567 static void *handle_neg(symbol_c *symbol, symbol_c *oper) {
   560 	DO_UNARY_OPER( int64, -, oper);	CHECK_OVERFLOW_int64_NEG(symbol, oper);
   568 	if (NULL == oper) return NULL;
   561 	/*
   569 	/* NOTE: The oper may never be an integer/real literal, '-1' and '-2.2' are stored as an neg_integer_c/neg_real_c instead.
   562 	 * NOTE : The syntax:   uint_v := -<INT_MIN>  may occur inside a neg_expression_c, but would always
   570 	 *       Because of this, we MUST NOT handle the INT_MIN special situation that is handled in neg_integer_c visitor!
   563 	 *        result in a data type error (in-> INT, out -> UINT). So, although we could handle it here, 
   571 	 *
   564 	 *        it is not really necessary as it will later be caught by the data type checking classes.
   572 	 *       VAR v1, v2, v3 : UINT; END_VAR;
       
   573 	 *       v1 =  9223372036854775808 ; (* |INT64_MIN| == -INT64_MIN *)   <------ LEGAL
       
   574 	 *       v2 =  -(-v1);                                                 <------ ILLEGAL (since it -v1 is overflow!)
       
   575 	 *       v2 =  -(-9223372036854775808 );                               <------ MUST also be ILLEGAL 
   565 	 */
   576 	 */
       
   577 	DO_UNARY_OPER(uint64, -, oper);	CHECK_OVERFLOW_uint64_NEG(symbol, oper);  /* handle the uint_v := -0 situation! */
       
   578 	DO_UNARY_OPER( int64, -, oper);	CHECK_OVERFLOW_int64_NEG (symbol, oper);
   566 	DO_UNARY_OPER(real64, -, oper);	CHECK_OVERFLOW_real64(symbol);
   579 	DO_UNARY_OPER(real64, -, oper);	CHECK_OVERFLOW_real64(symbol);
   567 	return NULL;
   580 	return NULL;
   568 }
   581 }
   569 
   582 
   570 
   583 
   577 }
   590 }
   578 
   591 
   579 
   592 
   580 static void *handle_or (symbol_c *symbol, symbol_c *oper1, symbol_c *oper2) {
   593 static void *handle_or (symbol_c *symbol, symbol_c *oper1, symbol_c *oper2) {
   581 	if ((NULL == oper1) || (NULL == oper2)) return NULL;
   594 	if ((NULL == oper1) || (NULL == oper2)) return NULL;
   582 	DO_BINARY_OPER_(  bool, ||, bool  , oper1, oper2);
   595 	DO_BINARY_OPER(  bool, ||, bool  , oper1, oper2);
   583 	DO_BINARY_OPER_(uint64, | , uint64, oper1, oper2);
   596 	DO_BINARY_OPER(uint64, | , uint64, oper1, oper2);
   584 	return NULL;
   597 	return NULL;
   585 }
   598 }
   586 
   599 
   587 
   600 
   588 static void *handle_xor(symbol_c *symbol, symbol_c *oper1, symbol_c *oper2) {
   601 static void *handle_xor(symbol_c *symbol, symbol_c *oper1, symbol_c *oper2) {
   589 	if ((NULL == oper1) || (NULL == oper2)) return NULL;
   602 	if ((NULL == oper1) || (NULL == oper2)) return NULL;
   590 	DO_BINARY_OPER_(  bool, ^, bool  , oper1, oper2);
   603 	DO_BINARY_OPER(  bool, ^, bool  , oper1, oper2);
   591 	DO_BINARY_OPER_(uint64, ^, uint64, oper1, oper2);
   604 	DO_BINARY_OPER(uint64, ^, uint64, oper1, oper2);
   592 	return NULL;
   605 	return NULL;
   593 }
   606 }
   594 
   607 
   595 
   608 
   596 static void *handle_and(symbol_c *symbol, symbol_c *oper1, symbol_c *oper2) {
   609 static void *handle_and(symbol_c *symbol, symbol_c *oper1, symbol_c *oper2) {
   597 	if ((NULL == oper1) || (NULL == oper2)) return NULL;
   610 	if ((NULL == oper1) || (NULL == oper2)) return NULL;
   598 	DO_BINARY_OPER_(  bool, &&, bool, oper1, oper2);
   611 	DO_BINARY_OPER(  bool, &&, bool, oper1, oper2);
   599 	DO_BINARY_OPER_(uint64, & , uint64, oper1, oper2);
   612 	DO_BINARY_OPER(uint64, & , uint64, oper1, oper2);
   600 	return NULL;
   613 	return NULL;
   601 }
   614 }
   602 
   615 
   603 
   616 
   604 static void *handle_add(symbol_c *symbol, symbol_c *oper1, symbol_c *oper2) {
   617 static void *handle_add(symbol_c *symbol, symbol_c *oper1, symbol_c *oper2) {
   605 	if ((NULL == oper1) || (NULL == oper2)) return NULL;
   618 	if ((NULL == oper1) || (NULL == oper2)) return NULL;
   606 	DO_BINARY_OPER_(uint64, +, uint64, oper1, oper2);   CHECK_OVERFLOW_uint64_SUM(symbol, oper1, oper2);
   619 	DO_BINARY_OPER(uint64, +, uint64, oper1, oper2);   CHECK_OVERFLOW_uint64_SUM(symbol, oper1, oper2);
   607 	DO_BINARY_OPER_( int64, +,  int64, oper1, oper2);   CHECK_OVERFLOW_int64_SUM (symbol, oper1, oper2);
   620 	DO_BINARY_OPER( int64, +,  int64, oper1, oper2);   CHECK_OVERFLOW_int64_SUM (symbol, oper1, oper2);
   608 	DO_BINARY_OPER_(real64, +, real64, oper1, oper2);   CHECK_OVERFLOW_real64    (symbol);
   621 	DO_BINARY_OPER(real64, +, real64, oper1, oper2);   CHECK_OVERFLOW_real64    (symbol);
   609 	return NULL;
   622 	return NULL;
   610 }
   623 }
   611 
   624 
   612 
   625 
   613 static void *handle_sub(symbol_c *symbol, symbol_c *oper1, symbol_c *oper2) {
   626 static void *handle_sub(symbol_c *symbol, symbol_c *oper1, symbol_c *oper2) {
   614 	if ((NULL == oper1) || (NULL == oper2)) return NULL;
   627 	if ((NULL == oper1) || (NULL == oper2)) return NULL;
   615 	DO_BINARY_OPER_(uint64, -, uint64, oper1, oper2);   CHECK_OVERFLOW_uint64_SUB(symbol, oper1, oper2);
   628 	DO_BINARY_OPER(uint64, -, uint64, oper1, oper2);   CHECK_OVERFLOW_uint64_SUB(symbol, oper1, oper2);
   616 	DO_BINARY_OPER_( int64, -,  int64, oper1, oper2);   CHECK_OVERFLOW_int64_SUB (symbol, oper1, oper2);
   629 	DO_BINARY_OPER( int64, -,  int64, oper1, oper2);   CHECK_OVERFLOW_int64_SUB (symbol, oper1, oper2);
   617 	DO_BINARY_OPER_(real64, -, real64, oper1, oper2);   CHECK_OVERFLOW_real64    (symbol);
   630 	DO_BINARY_OPER(real64, -, real64, oper1, oper2);   CHECK_OVERFLOW_real64    (symbol);
   618 	return NULL;
   631 	return NULL;
   619 }
   632 }
   620 
   633 
   621 
   634 
   622 static void *handle_mul(symbol_c *symbol, symbol_c *oper1, symbol_c *oper2) {
   635 static void *handle_mul(symbol_c *symbol, symbol_c *oper1, symbol_c *oper2) {
   623 	if ((NULL == oper1) || (NULL == oper2)) return NULL;
   636 	if ((NULL == oper1) || (NULL == oper2)) return NULL;
   624 	DO_BINARY_OPER_(uint64, *, uint64, oper1, oper2);   CHECK_OVERFLOW_uint64_MUL(symbol, oper1, oper2);
   637 	DO_BINARY_OPER(uint64, *, uint64, oper1, oper2);   CHECK_OVERFLOW_uint64_MUL(symbol, oper1, oper2);
   625 	DO_BINARY_OPER_( int64, *,  int64, oper1, oper2);   CHECK_OVERFLOW_int64_MUL (symbol, oper1, oper2);
   638 	DO_BINARY_OPER( int64, *,  int64, oper1, oper2);   CHECK_OVERFLOW_int64_MUL (symbol, oper1, oper2);
   626 	DO_BINARY_OPER_(real64, *, real64, oper1, oper2);   CHECK_OVERFLOW_real64    (symbol);
   639 	DO_BINARY_OPER(real64, *, real64, oper1, oper2);   CHECK_OVERFLOW_real64    (symbol);
   627 	return NULL;
   640 	return NULL;
   628 }
   641 }
   629 
   642 
   630 
   643 
   631 static void *handle_div(symbol_c *symbol, symbol_c *oper1, symbol_c *oper2) {
   644 static void *handle_div(symbol_c *symbol, symbol_c *oper1, symbol_c *oper2) {
   632 	if ((NULL == oper1) || (NULL == oper2)) return NULL;
   645 	if ((NULL == oper1) || (NULL == oper2)) return NULL;
   633 	if (ISZERO_CVALUE(uint64, oper2))  {SET_OVFLOW(uint64, symbol);} else {DO_BINARY_OPER_(uint64, /, uint64, oper1, oper2); CHECK_OVERFLOW_uint64_DIV(symbol, oper1, oper2);};
   646 	if (ISZERO_CVALUE(uint64, oper2))  {SET_OVFLOW(uint64, symbol);} else {DO_BINARY_OPER(uint64, /, uint64, oper1, oper2); CHECK_OVERFLOW_uint64_DIV(symbol, oper1, oper2);};
   634 	if (ISZERO_CVALUE( int64, oper2))  {SET_OVFLOW( int64, symbol);} else {DO_BINARY_OPER_( int64, /,  int64, oper1, oper2); CHECK_OVERFLOW_int64_DIV (symbol, oper1, oper2);};
   647 	if (ISZERO_CVALUE( int64, oper2))  {SET_OVFLOW( int64, symbol);} else {DO_BINARY_OPER( int64, /,  int64, oper1, oper2); CHECK_OVERFLOW_int64_DIV (symbol, oper1, oper2);};
   635 	if (ISZERO_CVALUE(real64, oper2))  {SET_OVFLOW(real64, symbol);} else {DO_BINARY_OPER_(real64, /, real64, oper1, oper2); CHECK_OVERFLOW_real64(symbol);};
   648 	if (ISZERO_CVALUE(real64, oper2))  {SET_OVFLOW(real64, symbol);} else {DO_BINARY_OPER(real64, /, real64, oper1, oper2); CHECK_OVERFLOW_real64(symbol);};
   636 	return NULL;
   649 	return NULL;
   637 }
   650 }
   638 
   651 
   639 
   652 
   640 static void *handle_mod(symbol_c *symbol, symbol_c *oper1, symbol_c *oper2) {
   653 static void *handle_mod(symbol_c *symbol, symbol_c *oper1, symbol_c *oper2) {
   643 	 *  IF (IN2 = 0) THEN OUT:=0 ; ELSE OUT:=IN1 - (IN1/IN2)*IN2 ; END_IF
   656 	 *  IF (IN2 = 0) THEN OUT:=0 ; ELSE OUT:=IN1 - (IN1/IN2)*IN2 ; END_IF
   644 	 *
   657 	 *
   645 	 * Note that, when IN1 = INT64_MIN, and IN2 = -1, an overflow occurs in the division,
   658 	 * Note that, when IN1 = INT64_MIN, and IN2 = -1, an overflow occurs in the division,
   646 	 * so although the MOD operation should be OK, acording to the above definition, we actually have an overflow!!
   659 	 * so although the MOD operation should be OK, acording to the above definition, we actually have an overflow!!
   647 	 */
   660 	 */
   648 	if (ISZERO_CVALUE(uint64, oper2))  {SET_CVALUE(uint64, symbol, 0);} else {DO_BINARY_OPER_(uint64, %, uint64, oper1, oper2); CHECK_OVERFLOW_uint64_MOD(symbol, oper1, oper2);};
   661 	if (ISZERO_CVALUE(uint64, oper2))  {SET_CVALUE(uint64, symbol, 0);} else {DO_BINARY_OPER(uint64, %, uint64, oper1, oper2); CHECK_OVERFLOW_uint64_MOD(symbol, oper1, oper2);};
   649 	if (ISZERO_CVALUE( int64, oper2))  {SET_CVALUE( int64, symbol, 0);} else {DO_BINARY_OPER_( int64, %,  int64, oper1, oper2); CHECK_OVERFLOW_int64_MOD (symbol, oper1, oper2);};
   662 	if (ISZERO_CVALUE( int64, oper2))  {SET_CVALUE( int64, symbol, 0);} else {DO_BINARY_OPER( int64, %,  int64, oper1, oper2); CHECK_OVERFLOW_int64_MOD (symbol, oper1, oper2);};
   650 	return NULL;
   663 	return NULL;
   651 }
   664 }
   652 
   665 
   653 
   666 
   654 static void *handle_pow(symbol_c *symbol, symbol_c *oper1, symbol_c *oper2) {
   667 static void *handle_pow(symbol_c *symbol, symbol_c *oper1, symbol_c *oper2) {
   754 }
   767 }
   755 
   768 
   756 
   769 
   757 void *constant_folding_c::visit(neg_real_c *symbol) {
   770 void *constant_folding_c::visit(neg_real_c *symbol) {
   758 	symbol->exp->accept(*this);
   771 	symbol->exp->accept(*this);
   759 	DO_UNARY_OPER(real64, -, symbol->exp);
   772 	DO_UNARY_OPER(real64, -, symbol->exp); CHECK_OVERFLOW_real64(symbol);
   760 	CHECK_OVERFLOW_real64(symbol);
   773 	if (IS_OVFLOW(real64, symbol->exp)) SET_OVFLOW(real64, symbol);
   761 	return NULL;
   774 	return NULL;
   762 }
   775 }
       
   776 
       
   777 
   763 
   778 
   764 /* | '-' integer	{$$ = new neg_integer_c($2, locloc(@$));} */
   779 /* | '-' integer	{$$ = new neg_integer_c($2, locloc(@$));} */
   765 void *constant_folding_c::visit(neg_integer_c *symbol) {
   780 void *constant_folding_c::visit(neg_integer_c *symbol) {
   766 	symbol->exp->accept(*this);
   781 	symbol->exp->accept(*this);
   767 	DO_UNARY_OPER(int64, -, symbol->exp);
   782 	/* Note that due to syntax restrictions, the value of symbol->exp will always be positive. 
   768 	CHECK_OVERFLOW_int64_NEG(symbol, symbol->exp);
   783 	 * However, the following code does not depend on that restriction.
       
   784 	 */
       
   785 	/* The remainder of the code (for example, data type checking) considers the neg_integer_c as a leaf of the
       
   786 	 * abstract syntax tree, and therefore simply ignores the values of neg_integer_c->exp.
       
   787 	 * For this reason only, and in only this situation, we must guarantee that any 'overflow' situation in 
       
   788 	 * the cvalue of neg_integer_c->exp is also reflected back to this neg_integer_c symbol.
       
   789 	 * For the rest of the code we do NOT do this, as it would gurantee that a single overflow deep inside
       
   790 	 * an expression would imply that the expression itself would also be set to 'overflow' condition.
       
   791 	 * This in turn would then have the compiler produce a whole load of error messages where they are not wanted!
       
   792 	 */
       
   793 	DO_UNARY_OPER(uint64, -, symbol->exp); CHECK_OVERFLOW_uint64_NEG(symbol, symbol->exp);  /* handle the uintv := -0 situation */
       
   794 	if (IS_OVFLOW(uint64, symbol->exp)) SET_OVFLOW(uint64, symbol);
       
   795 	DO_UNARY_OPER( int64, -, symbol->exp); CHECK_OVERFLOW_int64_NEG (symbol, symbol->exp);
       
   796 	if (IS_OVFLOW( int64, symbol->exp)) SET_OVFLOW( int64, symbol);
   769 	/* NOTE 1: INT64_MIN = -(INT64_MAX + 1)   ---> assuming two's complement representation!!!
   797 	/* NOTE 1: INT64_MIN = -(INT64_MAX + 1)   ---> assuming two's complement representation!!!
   770 	 * NOTE 2: if the user happens to want INT_MIN, that value will first be parsed as a positive integer, before being negated here.
   798 	 * NOTE 2: if the user happens to want INT_MIN, that value will first be parsed as a positive integer, before being negated here.
   771 	 * However, the positive value cannot be stored inside an int64! So, in this case, we will get the value from the uint64 cvalue.
   799 	 * However, the positive value cannot be stored inside an int64! So, in this case, we will get the value from the uint64 cvalue.
       
   800 	 *
       
   801 	 * This same situation is usually considered an overflow (check handle_neg() function). However, here we have a special
       
   802 	 * situation. If we do not allow this, then the user would never the able to use the following code:
       
   803 	 *  VAR v : LINT; END_VAR
       
   804 	 *    v := -9223372036854775809 ; (* - |INT64_MIN| == INT64_MIN *)
   772 	 */
   805 	 */
   773 	// if (INT64_MIN == -INT64_MAX - 1) // We do not really need to check that the platform uses two's complement
   806 	// if (INT64_MIN == -INT64_MAX - 1) // We do not really need to check that the platform uses two's complement
   774 	if (VALID_CVALUE(uint64, symbol->exp) && (GET_CVALUE(uint64, symbol->exp) == (uint64_t)INT64_MAX+1)) {
   807 	if (VALID_CVALUE(uint64, symbol->exp) && (GET_CVALUE(uint64, symbol->exp) == (uint64_t)INT64_MAX+1)) {
   775 		SET_CVALUE(int64, symbol, INT64_MIN);
   808 		SET_CVALUE(int64, symbol, INT64_MIN);
   776 	}
   809 	}
   777 	/* NOTE 3: The standard allows considers the following strange syntax correct:
       
   778 	 *            int_v = ----------42;
       
   779 	 *         However, it will be parsed as multiple neg_expression_c, with a single final neg_integer_c.
       
   780 	 *         So, when parsing a neg_integer_c, we are guaranteed to always have a positive value in symbol->exp
       
   781 	 *         --> Conclusion: 
       
   782 	 *         We do not need to handle the situation where we are negating the INT_MIN value, whose
       
   783 	 *         result can only be stored inside an UINT (remember that INT_MIN is < 0 !!).
       
   784 	 *
       
   785 	 * NOTE 4: The syntax:   uint_v := -<INT_MIN>  may occur inside a neg_expression_c, but would always
       
   786 	 *         result in a data type error. So, although we could handle it here, it is not really
       
   787 	 *         necessary as it will later be caught by the data type checking classes.
       
   788 	 */
       
   789 	return NULL;
   810 	return NULL;
   790 }
   811 }
   791 
   812 
   792 
   813 
   793 void *constant_folding_c::visit(binary_integer_c *symbol) {
   814 void *constant_folding_c::visit(binary_integer_c *symbol) {