stage3/constant_folding.cc
changeset 612 c062ff18d04f
parent 607 be9ba3531afb
child 621 e3616f6b6959
equal deleted inserted replaced
611:8e81d7db54be 612:c062ff18d04f
   163 
   163 
   164 
   164 
   165 
   165 
   166 
   166 
   167 
   167 
   168 #define NEW_CVALUE(dtype, symbol) \
   168 #define SET_CVALUE(dtype, symbol, new_value)  ((symbol)->const_value._##dtype.value) = new_value; ((symbol)->const_value._##dtype.status) = symbol_c::cs_const_value;
   169  (symbol->const_value_##dtype) = new(symbol_c::const_value_##dtype##_t); \
   169 #define GET_CVALUE(dtype, symbol)             ((symbol)->const_value._##dtype.value)
   170  if ((symbol->const_value_##dtype) == NULL) ERROR; \
   170 #define SET_OVFLOW(dtype, symbol)             ((symbol)->const_value._##dtype.status) = symbol_c::cs_overflow
   171  (symbol->const_value_##dtype)->status = symbol_c::cs_undefined;
   171 #define SET_NONCONST(dtype, symbol)           ((symbol)->const_value._##dtype.status) = symbol_c::cs_non_const
   172 
   172 
   173 #define SET_CVALUE(dtype, symbol, new_value)  ((symbol)->const_value_##dtype->value) = new_value; ((symbol)->const_value_##dtype->status) = symbol_c::cs_const_value;
   173 #define VALID_CVALUE(dtype, symbol)           (symbol_c::cs_const_value == (symbol)->const_value._##dtype.status)
   174 #define GET_CVALUE(dtype, symbol)             ((symbol)->const_value_##dtype->value)
       
   175 #define SET_OVFLOW(dtype, symbol)             ((symbol)->const_value_##dtype->status) = symbol_c::cs_overflow
       
   176     /* 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 #define VALID_CVALUE(dtype, symbol)           ((NULL != (symbol)->const_value_##dtype) && (symbol_c::cs_const_value == (symbol)->const_value_##dtype->status))
       
   178 #define ISZERO_CVALUE(dtype, symbol)          ((VALID_CVALUE(dtype, symbol)) && (GET_CVALUE(dtype, symbol) == 0))
   174 #define ISZERO_CVALUE(dtype, symbol)          ((VALID_CVALUE(dtype, symbol)) && (GET_CVALUE(dtype, symbol) == 0))
       
   175 
       
   176 #define ISEQUAL_CVALUE(dtype, symbol1, symbol2) \
       
   177 	(VALID_CVALUE(dtype, symbol1) && VALID_CVALUE(dtype, symbol2) && (GET_CVALUE(dtype, symbol1) == GET_CVALUE(dtype, symbol2))) 
   179 
   178 
   180 #define DO_BINARY_OPER(dtype, oper, otype)\
   179 #define DO_BINARY_OPER(dtype, oper, otype)\
   181 	if (VALID_CVALUE(dtype, symbol->r_exp) && VALID_CVALUE(dtype, symbol->l_exp)) {                                \
   180 	if (VALID_CVALUE(dtype, symbol->r_exp) && VALID_CVALUE(dtype, symbol->l_exp)) {                                \
   182 		NEW_CVALUE(otype, symbol);                                                                             \
       
   183 		SET_CVALUE(otype, symbol, GET_CVALUE(dtype, symbol->l_exp) oper GET_CVALUE(dtype, symbol->r_exp));     \
   181 		SET_CVALUE(otype, symbol, GET_CVALUE(dtype, symbol->l_exp) oper GET_CVALUE(dtype, symbol->r_exp));     \
   184 	}
   182 	}
   185 
   183 
   186 #define DO_UNARY_OPER(dtype, oper, arg)\
   184 #define DO_BINARY_OPER_(oper_type, operation, res_type, operand1, operand2)\
   187 	if (VALID_CVALUE(dtype, arg)) {                                                                                \
   185 	if (VALID_CVALUE(oper_type, operand1) && VALID_CVALUE(oper_type, operand2)) {                                     \
   188 		NEW_CVALUE(dtype, symbol);                                                                             \
   186 		SET_CVALUE(res_type, symbol, GET_CVALUE(oper_type, operand1) operation GET_CVALUE(oper_type, operand2));  \
   189 		SET_CVALUE(dtype, symbol, oper GET_CVALUE(dtype, arg));                                                \
   187 	}
       
   188 
       
   189 #define DO_UNARY_OPER(dtype, operation, operand)\
       
   190 	if (VALID_CVALUE(dtype, operand)) {                                                                               \
       
   191 		SET_CVALUE(dtype, symbol, operation GET_CVALUE(dtype, operand));                                          \
   190 	}
   192 	}
   191 
   193 
   192 
   194 
   193 
   195 
   194 
   196 
   510 }
   512 }
   511 
   513 
   512 
   514 
   513 
   515 
   514 
   516 
       
   517 /***********************************************************************/
       
   518 /***********************************************************************/
       
   519 /***********************************************************************/
       
   520 /***        Functions to execute operations on the const values      ***/
       
   521 /***********************************************************************/
       
   522 /***********************************************************************/
       
   523 /***********************************************************************/
       
   524 
       
   525 /* static void *handle_cmp(symbol_c *symbol, symbol_c *oper1, symbol_c *oper2, OPERATION) */
       
   526 #define handle_cmp(symbol, oper1, oper2, operation) {               \
       
   527 	if ((NULL == oper1) || (NULL == oper2)) return NULL;        \
       
   528 	DO_BINARY_OPER_(  bool, operation, bool, oper1, oper2);     \
       
   529 	DO_BINARY_OPER_(uint64, operation, bool, oper1, oper2);     \
       
   530 	DO_BINARY_OPER_( int64, operation, bool, oper1, oper2);     \
       
   531 	DO_BINARY_OPER_(real64, operation, bool, oper1, oper2);     \
       
   532 	return NULL;                                                \
       
   533 }
       
   534 
       
   535 
       
   536 /* NOTE: the MOVE standard function is equivalent to the ':=' in ST syntax */
       
   537 static void *handle_move(symbol_c *to, symbol_c *from) {
       
   538 	if (NULL == from) return NULL;
       
   539 	to->const_value = from->const_value;
       
   540 	return NULL;
       
   541 }
       
   542 
       
   543 
       
   544 /* unary negation (multiply by -1) */
       
   545 static void *handle_neg(symbol_c *symbol, symbol_c *oper) {
       
   546 	DO_UNARY_OPER( int64, -, oper);	CHECK_OVERFLOW_int64_NEG(symbol, oper);
       
   547 	DO_UNARY_OPER(real64, -, oper);	CHECK_OVERFLOW_real64(symbol);
       
   548 	return NULL;
       
   549 }
       
   550 
       
   551 
       
   552 /* unary boolean negation (NOT) */
       
   553 static void *handle_not(symbol_c *symbol, symbol_c *oper) {
       
   554 	if (NULL == oper) return NULL;
       
   555 	DO_UNARY_OPER(  bool, !, oper);
       
   556 	DO_UNARY_OPER(uint64, ~, oper);
       
   557 	return NULL;
       
   558 }
       
   559 
       
   560 
       
   561 static void *handle_or (symbol_c *symbol, symbol_c *oper1, symbol_c *oper2) {
       
   562 	if ((NULL == oper1) || (NULL == oper2)) return NULL;
       
   563 	DO_BINARY_OPER_(  bool, ||, bool  , oper1, oper2);
       
   564 	DO_BINARY_OPER_(uint64, | , uint64, oper1, oper2);
       
   565 	return NULL;
       
   566 }
       
   567 
       
   568 
       
   569 static void *handle_xor(symbol_c *symbol, symbol_c *oper1, symbol_c *oper2) {
       
   570 	if ((NULL == oper1) || (NULL == oper2)) return NULL;
       
   571 	DO_BINARY_OPER_(  bool, ^, bool  , oper1, oper2);
       
   572 	DO_BINARY_OPER_(uint64, ^, uint64, oper1, oper2);
       
   573 	return NULL;
       
   574 }
       
   575 
       
   576 
       
   577 static void *handle_and(symbol_c *symbol, symbol_c *oper1, symbol_c *oper2) {
       
   578 	if ((NULL == oper1) || (NULL == oper2)) return NULL;
       
   579 	DO_BINARY_OPER_(  bool, &&, bool, oper1, oper2);
       
   580 	DO_BINARY_OPER_(uint64, & , uint64, oper1, oper2);
       
   581 	return NULL;
       
   582 }
       
   583 
       
   584 
       
   585 static void *handle_add(symbol_c *symbol, symbol_c *oper1, symbol_c *oper2) {
       
   586 	if ((NULL == oper1) || (NULL == oper2)) return NULL;
       
   587 	DO_BINARY_OPER_(uint64, +, uint64, oper1, oper2);   CHECK_OVERFLOW_uint64_SUM(symbol, oper1, oper2);
       
   588 	DO_BINARY_OPER_( int64, +,  int64, oper1, oper2);   CHECK_OVERFLOW_int64_SUM (symbol, oper1, oper2);
       
   589 	DO_BINARY_OPER_(real64, +, real64, oper1, oper2);   CHECK_OVERFLOW_real64    (symbol);
       
   590 	return NULL;
       
   591 }
       
   592 
       
   593 
       
   594 static void *handle_sub(symbol_c *symbol, symbol_c *oper1, symbol_c *oper2) {
       
   595 	if ((NULL == oper1) || (NULL == oper2)) return NULL;
       
   596 	DO_BINARY_OPER_(uint64, -, uint64, oper1, oper2);   CHECK_OVERFLOW_uint64_SUB(symbol, oper1, oper2);
       
   597 	DO_BINARY_OPER_( int64, -,  int64, oper1, oper2);   CHECK_OVERFLOW_int64_SUB (symbol, oper1, oper2);
       
   598 	DO_BINARY_OPER_(real64, -, real64, oper1, oper2);   CHECK_OVERFLOW_real64    (symbol);
       
   599 	return NULL;
       
   600 }
       
   601 
       
   602 
       
   603 static void *handle_mul(symbol_c *symbol, symbol_c *oper1, symbol_c *oper2) {
       
   604 	if ((NULL == oper1) || (NULL == oper2)) return NULL;
       
   605 	DO_BINARY_OPER_(uint64, *, uint64, oper1, oper2);   CHECK_OVERFLOW_uint64_MUL(symbol, oper1, oper2);
       
   606 	DO_BINARY_OPER_( int64, *,  int64, oper1, oper2);   CHECK_OVERFLOW_int64_MUL (symbol, oper1, oper2);
       
   607 	DO_BINARY_OPER_(real64, *, real64, oper1, oper2);   CHECK_OVERFLOW_real64    (symbol);
       
   608 	return NULL;
       
   609 }
       
   610 
       
   611 
       
   612 static void *handle_div(symbol_c *symbol, symbol_c *oper1, symbol_c *oper2) {
       
   613 	if ((NULL == oper1) || (NULL == oper2)) return NULL;
       
   614 	if (ISZERO_CVALUE(uint64, oper2))  {SET_OVFLOW(uint64, symbol);} else {DO_BINARY_OPER_(uint64, /, uint64, oper1, oper2); CHECK_OVERFLOW_uint64_DIV(symbol, oper1, oper2);};
       
   615 	if (ISZERO_CVALUE( int64, oper2))  {SET_OVFLOW( int64, symbol);} else {DO_BINARY_OPER_( int64, /,  int64, oper1, oper2); CHECK_OVERFLOW_int64_DIV (symbol, oper1, oper2);};
       
   616 	if (ISZERO_CVALUE(real64, oper2))  {SET_OVFLOW(real64, symbol);} else {DO_BINARY_OPER_(real64, /, real64, oper1, oper2); CHECK_OVERFLOW_real64(symbol);};
       
   617 	return NULL;
       
   618 }
       
   619 
       
   620 
       
   621 static void *handle_mod(symbol_c *symbol, symbol_c *oper1, symbol_c *oper2) {
       
   622 	if ((NULL == oper1) || (NULL == oper2)) return NULL;
       
   623 	/* IEC 61131-3 standard says IN1 MOD IN2 must be equivalent to
       
   624 	 *  IF (IN2 = 0) THEN OUT:=0 ; ELSE OUT:=IN1 - (IN1/IN2)*IN2 ; END_IF
       
   625 	 *
       
   626 	 * Note that, when IN1 = INT64_MIN, and IN2 = -1, an overflow occurs in the division,
       
   627 	 * so although the MOD operation should be OK, acording to the above definition, we actually have an overflow!!
       
   628 	 */
       
   629 	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);};
       
   630 	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);};
       
   631 	return NULL;
       
   632 }
       
   633 
       
   634 
       
   635 static void *handle_pow(symbol_c *symbol, symbol_c *oper1, symbol_c *oper2) {
       
   636 	/* NOTE: If the const_value in symbol->r_exp is within the limits of both int64 and uint64, then we do both operations.
       
   637 	 *       That is OK, as the result should be identicial (we do create an unnecessary CVALUE variable, but who cares?).
       
   638 	 *       If only one is valid, then that is the oper we will do!
       
   639 	 */
       
   640 	if (VALID_CVALUE(real64, oper1) && VALID_CVALUE( int64, oper2))
       
   641 		SET_CVALUE(real64, symbol, pow(GET_CVALUE(real64, oper1), GET_CVALUE( int64, oper2)));
       
   642 	if (VALID_CVALUE(real64, oper1) && VALID_CVALUE(uint64, oper2))
       
   643 		SET_CVALUE(real64, symbol, pow(GET_CVALUE(real64, oper1), GET_CVALUE(uint64, oper2)));
       
   644 	CHECK_OVERFLOW_real64(symbol);
       
   645 	return NULL;
       
   646 }
       
   647 
       
   648 /***********************************************************************/
       
   649 /***********************************************************************/
       
   650 /***********************************************************************/
       
   651 /***        Helper functions for handling IL instruction lists.      ***/
       
   652 /***********************************************************************/
       
   653 /***********************************************************************/
       
   654 /***********************************************************************/
       
   655 
       
   656 
       
   657 /* If the cvalues of all the prev_il_intructions have the same VALID value, then set the local cvalue to that value, otherwise, set it to NONCONST! */
       
   658 #define intersect_prev_CVALUE_(dtype, symbol) {                                                                   \
       
   659 	symbol->const_value._##dtype = symbol->prev_il_instruction[0]->const_value._##dtype;                      \
       
   660 	for (unsigned int i = 1; i < symbol->prev_il_instruction.size(); i++) {                                   \
       
   661 		if (!ISEQUAL_CVALUE(dtype, symbol, symbol->prev_il_instruction[i]))                               \
       
   662 			{SET_NONCONST(dtype, symbol); break;}                                                     \
       
   663 	}                                                                                                         \
       
   664 }
       
   665 
       
   666 static void intersect_prev_cvalues(il_instruction_c *symbol) {
       
   667 	if (symbol->prev_il_instruction.empty())
       
   668 		return;
       
   669 	intersect_prev_CVALUE_(real64, symbol);
       
   670 	intersect_prev_CVALUE_(uint64, symbol);
       
   671 	intersect_prev_CVALUE_( int64, symbol);
       
   672 	intersect_prev_CVALUE_(  bool, symbol);
       
   673 }
   515 
   674 
   516 
   675 
   517 
   676 
   518 /***********************************************************************/
   677 /***********************************************************************/
   519 /***********************************************************************/
   678 /***********************************************************************/
   558 /******************************/
   717 /******************************/
   559 /* B 1.2.1 - Numeric Literals */
   718 /* B 1.2.1 - Numeric Literals */
   560 /******************************/
   719 /******************************/
   561 void *constant_folding_c::visit(real_c *symbol) {
   720 void *constant_folding_c::visit(real_c *symbol) {
   562 	bool overflow;
   721 	bool overflow;
   563 	NEW_CVALUE(real64, symbol);	SET_CVALUE(real64, symbol, extract_real_value(symbol, &overflow));
   722 	SET_CVALUE(real64, symbol, extract_real_value(symbol, &overflow));
   564 	if (overflow) SET_OVFLOW(real64, symbol);
   723 	if (overflow) SET_OVFLOW(real64, symbol);
   565 	return NULL;
   724 	return NULL;
   566 }
   725 }
   567 
   726 
   568 
   727 
   569 void *constant_folding_c::visit(integer_c *symbol) {
   728 void *constant_folding_c::visit(integer_c *symbol) {
   570 	bool overflow;
   729 	bool overflow;
   571 	NEW_CVALUE( int64, symbol);	SET_CVALUE( int64, symbol, extract_int64_value (symbol, &overflow));
   730 	SET_CVALUE( int64, symbol, extract_int64_value (symbol, &overflow));
   572 	if (overflow) SET_OVFLOW(int64, symbol);
   731 	if (overflow) SET_OVFLOW(int64, symbol);
   573 	NEW_CVALUE(uint64, symbol);	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow));
   732 	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow));
   574 	if (overflow) SET_OVFLOW(uint64, symbol);
   733 	if (overflow) SET_OVFLOW(uint64, symbol);
   575 	return NULL;
   734 	return NULL;
   576 }
   735 }
   577 
   736 
   578 
   737 
   592 	 * NOTE 2: if the user happens to want INT_MIN, that value will first be parsed as a positive integer, before being negated here.
   751 	 * NOTE 2: if the user happens to want INT_MIN, that value will first be parsed as a positive integer, before being negated here.
   593 	 * However, the positive value cannot be stored inside an int64! So, in this case, we will get the value from the uint64 cvalue.
   752 	 * However, the positive value cannot be stored inside an int64! So, in this case, we will get the value from the uint64 cvalue.
   594 	 */
   753 	 */
   595 	// if (INT64_MIN == -INT64_MAX - 1) // We do not really need to check that the platform uses two's complement
   754 	// if (INT64_MIN == -INT64_MAX - 1) // We do not really need to check that the platform uses two's complement
   596 	if (VALID_CVALUE(uint64, symbol->exp) && (GET_CVALUE(uint64, symbol->exp) == -INT64_MIN)) { // How do we stop the compiler from complaining about a comparison between int and unsigned int?
   755 	if (VALID_CVALUE(uint64, symbol->exp) && (GET_CVALUE(uint64, symbol->exp) == -INT64_MIN)) { // How do we stop the compiler from complaining about a comparison between int and unsigned int?
   597 		NEW_CVALUE(int64, symbol); // in principle, if the above condition is true, then no new cvalue was created by DO_UNARY_OPER(). Not that it would be a problem to create a new one!
       
   598 		SET_CVALUE(int64, symbol, INT64_MIN);
   756 		SET_CVALUE(int64, symbol, INT64_MIN);
   599 	}
   757 	}
   600 	return NULL;
   758 	return NULL;
   601 }
   759 }
   602 
   760 
   603 
   761 
   604 void *constant_folding_c::visit(binary_integer_c *symbol) {
   762 void *constant_folding_c::visit(binary_integer_c *symbol) {
   605 	bool overflow;
   763 	bool overflow;
   606 	NEW_CVALUE( int64, symbol);	SET_CVALUE( int64, symbol, extract_int64_value (symbol, &overflow));
   764 	SET_CVALUE( int64, symbol, extract_int64_value (symbol, &overflow));
   607 	if (overflow) SET_OVFLOW(int64, symbol);
   765 	if (overflow) SET_OVFLOW(int64, symbol);
   608 	NEW_CVALUE(uint64, symbol);	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow));
   766 	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow));
   609 	if (overflow) SET_OVFLOW(uint64, symbol);
   767 	if (overflow) SET_OVFLOW(uint64, symbol);
   610 	return NULL;
   768 	return NULL;
   611 }
   769 }
   612 
   770 
   613 
   771 
   614 void *constant_folding_c::visit(octal_integer_c *symbol) {
   772 void *constant_folding_c::visit(octal_integer_c *symbol) {
   615 	bool overflow;
   773 	bool overflow;
   616 	NEW_CVALUE( int64, symbol);	SET_CVALUE( int64, symbol, extract_int64_value (symbol, &overflow));
   774 	SET_CVALUE( int64, symbol, extract_int64_value (symbol, &overflow));
   617 	if (overflow) SET_OVFLOW(int64, symbol);
   775 	if (overflow) SET_OVFLOW(int64, symbol);
   618 	NEW_CVALUE(uint64, symbol);	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow));
   776 	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow));
   619 	if (overflow) SET_OVFLOW(uint64, symbol);
   777 	if (overflow) SET_OVFLOW(uint64, symbol);
   620 	return NULL;
   778 	return NULL;
   621 }
   779 }
   622 
   780 
   623 
   781 
   624 void *constant_folding_c::visit(hex_integer_c *symbol) {
   782 void *constant_folding_c::visit(hex_integer_c *symbol) {
   625 	bool overflow;
   783 	bool overflow;
   626 	NEW_CVALUE( int64, symbol);	SET_CVALUE( int64, symbol, extract_int64_value (symbol, &overflow));
   784 	SET_CVALUE( int64, symbol, extract_int64_value (symbol, &overflow));
   627 	if (overflow) SET_OVFLOW(int64, symbol);
   785 	if (overflow) SET_OVFLOW(int64, symbol);
   628 	NEW_CVALUE(uint64, symbol);	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow));
   786 	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow));
   629 	if (overflow) SET_OVFLOW(uint64, symbol);
   787 	if (overflow) SET_OVFLOW(uint64, symbol);
   630 	return NULL;
   788 	return NULL;
   631 }
   789 }
   632 
   790 
   633 
   791 
   665 	return NULL;
   823 	return NULL;
   666 }
   824 }
   667 
   825 
   668 
   826 
   669 void *constant_folding_c::visit(boolean_true_c *symbol) {
   827 void *constant_folding_c::visit(boolean_true_c *symbol) {
   670 	NEW_CVALUE(bool, symbol);	SET_CVALUE(bool, symbol, true);
   828 	SET_CVALUE(bool, symbol, true);
   671 	return NULL;
   829 	return NULL;
   672 }
   830 }
   673 
   831 
   674 
   832 
   675 void *constant_folding_c::visit(boolean_false_c *symbol) {
   833 void *constant_folding_c::visit(boolean_false_c *symbol) {
   676 	NEW_CVALUE(bool, symbol);	SET_CVALUE(bool, symbol, false);
   834 	SET_CVALUE(bool, symbol, false);
   677 	return NULL;
   835 	return NULL;
   678 }
   836 }
       
   837 
       
   838 
       
   839 
       
   840 
       
   841 
       
   842 /****************************************/
       
   843 /* B.2 - Language IL (Instruction List) */
       
   844 /****************************************/
       
   845 /***********************************/
       
   846 /* B 2.1 Instructions and Operands */
       
   847 /***********************************/
       
   848 /* Not needed, since we inherit from iterator_visitor_c */
       
   849 /*| instruction_list il_instruction */
       
   850 // SYM_LIST(instruction_list_c)
       
   851 // void *constant_folding_c::visit(instruction_list_c *symbol) {}
       
   852 
       
   853 /* | label ':' [il_incomplete_instruction] eol_list */
       
   854 // SYM_REF2(il_instruction_c, label, il_instruction)
       
   855 // void *visit(instruction_list_c *symbol);
       
   856 void *constant_folding_c::visit(il_instruction_c *symbol) {
       
   857 	if (NULL == symbol->il_instruction) {
       
   858 		/* This empty/null il_instruction does not change the value of the current/default IL variable.
       
   859 		 * So it inherits the candidate_datatypes from it's previous IL instructions!
       
   860 		 */
       
   861 		intersect_prev_cvalues(symbol);
       
   862 	} else {
       
   863 		il_instruction_c fake_prev_il_instruction = *symbol;
       
   864 		intersect_prev_cvalues(&fake_prev_il_instruction);
       
   865 
       
   866 		if (symbol->prev_il_instruction.size() == 0)  prev_il_instruction = NULL;
       
   867 		else                                          prev_il_instruction = &fake_prev_il_instruction;
       
   868 		symbol->il_instruction->accept(*this);
       
   869 		prev_il_instruction = NULL;
       
   870 
       
   871 		/* This object has (inherits) the same cvalues as the il_instruction */
       
   872 		symbol->const_value = symbol->il_instruction->const_value;
       
   873 	}
       
   874 
       
   875 	return NULL;
       
   876 }
       
   877 
       
   878 
       
   879 void *constant_folding_c::visit(il_simple_operation_c *symbol) {
       
   880 	/* determine the cvalue of the operand */
       
   881 	if (NULL != symbol->il_operand) {
       
   882 		symbol->il_operand->accept(*this);
       
   883 	}
       
   884 	/* determine the cvalue resulting from executing the il_operator... */
       
   885 	il_operand = symbol->il_operand;
       
   886 	symbol->il_simple_operator->accept(*this);
       
   887 	il_operand = NULL;
       
   888 	/* This object has (inherits) the same cvalues as the il_instruction */
       
   889 	symbol->const_value = symbol->il_simple_operator->const_value;
       
   890 	return NULL;
       
   891 }
       
   892 
       
   893 
       
   894 /* TODO: handle function invocations... */
       
   895 /* | function_name [il_operand_list] */
       
   896 /* NOTE: The parameters 'called_function_declaration' and 'extensible_param_count' are used to pass data between the stage 3 and stage 4. */
       
   897 // SYM_REF2(il_function_call_c, function_name, il_operand_list, symbol_c *called_function_declaration; int extensible_param_count;)
       
   898 // void *constant_folding_c::visit(il_function_call_c *symbol) {}
       
   899 
       
   900 
       
   901 /* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */
       
   902 // SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list);
       
   903 void *constant_folding_c::visit(il_expression_c *symbol) {
       
   904   symbol_c *prev_il_instruction_backup = prev_il_instruction;
       
   905   
       
   906   if (NULL != symbol->il_operand)
       
   907     symbol->il_operand->accept(*this);
       
   908 
       
   909   if(symbol->simple_instr_list != NULL)
       
   910     symbol->simple_instr_list->accept(*this);
       
   911 
       
   912   /* Now do the operation,  */
       
   913   il_operand = symbol->simple_instr_list;
       
   914   prev_il_instruction = prev_il_instruction_backup;
       
   915   symbol->il_expr_operator->accept(*this);
       
   916   il_operand = NULL;
       
   917   
       
   918   /* This object has (inherits) the same cvalues as the il_instruction */
       
   919   symbol->const_value = symbol->il_expr_operator->const_value;
       
   920   return NULL;
       
   921 }
       
   922 
       
   923 
       
   924 
       
   925 void *constant_folding_c::visit(il_jump_operation_c *symbol) {
       
   926   /* recursive call to fill const values... */
       
   927   il_operand = NULL;
       
   928   symbol->il_jump_operator->accept(*this);
       
   929   il_operand = NULL;
       
   930   /* This object has (inherits) the same cvalues as the il_jump_operator */
       
   931   symbol->const_value = symbol->il_jump_operator->const_value;
       
   932   return NULL;
       
   933 }
       
   934 
       
   935 
       
   936 
       
   937 /* FB calls leave the value in the accumulator unchanged */
       
   938 /*   il_call_operator prev_declared_fb_name
       
   939  * | il_call_operator prev_declared_fb_name '(' ')'
       
   940  * | il_call_operator prev_declared_fb_name '(' eol_list ')'
       
   941  * | il_call_operator prev_declared_fb_name '(' il_operand_list ')'
       
   942  * | il_call_operator prev_declared_fb_name '(' eol_list il_param_list ')'
       
   943  */
       
   944 /* NOTE: The parameter 'called_fb_declaration'is used to pass data between stage 3 and stage4 (although currently it is not used in stage 4 */
       
   945 // SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list, symbol_c *called_fb_declaration)
       
   946 void *constant_folding_c::visit(il_fb_call_c *symbol) {return handle_move(symbol, prev_il_instruction);}
       
   947 
       
   948 
       
   949 /* TODO: handle function invocations... */
       
   950 /* | function_name '(' eol_list [il_param_list] ')' */
       
   951 /* NOTE: The parameter 'called_function_declaration' is used to pass data between the stage 3 and stage 4. */
       
   952 // SYM_REF2(il_formal_funct_call_c, function_name, il_param_list, symbol_c *called_function_declaration; int extensible_param_count;)
       
   953 // void *constant_folding_c::visit(il_formal_funct_call_c *symbol) {return NULL;}
       
   954 
       
   955 
       
   956 
       
   957 /* Not needed, since we inherit from iterator_visitor_c */
       
   958 //  void *constant_folding_c::visit(il_operand_list_c *symbol);
       
   959 
       
   960 
       
   961 
       
   962 /* | simple_instr_list il_simple_instruction */
       
   963 /* This object is referenced by il_expression_c objects */
       
   964 void *constant_folding_c::visit(simple_instr_list_c *symbol) {
       
   965   if (symbol->n <= 0)
       
   966     return NULL;  /* List is empty! Nothing to do. */
       
   967     
       
   968   for(int i = 0; i < symbol->n; i++)
       
   969     symbol->elements[i]->accept(*this);
       
   970 
       
   971   /* This object has (inherits) the same cvalues as the il_jump_operator */
       
   972   symbol->const_value = symbol->elements[symbol->n-1]->const_value;
       
   973   return NULL;
       
   974 }
       
   975 
       
   976 
       
   977 
       
   978 // SYM_REF1(il_simple_instruction_c, il_simple_instruction, symbol_c *prev_il_instruction;)
       
   979 void *constant_folding_c::visit(il_simple_instruction_c *symbol) {
       
   980   if (symbol->prev_il_instruction.size() > 1) ERROR; /* There should be no labeled insructions inside an IL expression! */
       
   981   if (symbol->prev_il_instruction.size() == 0)  prev_il_instruction = NULL;
       
   982   else                                          prev_il_instruction = symbol->prev_il_instruction[0];
       
   983   symbol->il_simple_instruction->accept(*this);
       
   984   prev_il_instruction = NULL;
       
   985 
       
   986   /* This object has (inherits) the same cvalues as the il_jump_operator */
       
   987   symbol->const_value = symbol->il_simple_instruction->const_value;
       
   988   return NULL;
       
   989 }
       
   990 
       
   991 
       
   992 /*
       
   993     void *visit(il_param_list_c *symbol);
       
   994     void *visit(il_param_assignment_c *symbol);
       
   995     void *visit(il_param_out_assignment_c *symbol);
       
   996 */
       
   997 
       
   998 
       
   999 /*******************/
       
  1000 /* B 2.2 Operators */
       
  1001 /*******************/
       
  1002 void *constant_folding_c::visit(   LD_operator_c *symbol) {return handle_move(symbol, il_operand);}
       
  1003 void *constant_folding_c::visit(  LDN_operator_c *symbol) {return handle_not (symbol, il_operand);}
       
  1004 
       
  1005 /* NOTE: we are implementing a constant folding algorithm, not a constant propagation algorithm.
       
  1006  *       For the constant propagation algorithm, the correct implementation of ST(N)_operator_c would be...
       
  1007  */
       
  1008 //void *constant_folding_c::visit(   ST_operator_c *symbol) {return handle_move(il_operand, symbol);}
       
  1009 //void *constant_folding_c::visit(  STN_operator_c *symbol) {return handle_not (il_operand, symbol);}
       
  1010 void *constant_folding_c::visit(   ST_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
       
  1011 void *constant_folding_c::visit(  STN_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
       
  1012 
       
  1013 /* NOTE: the standard allows syntax in which the NOT operator is followed by an optional <il_operand>
       
  1014  *              NOT [<il_operand>]
       
  1015  *       However, it does not define the semantic of the NOT operation when the <il_operand> is specified.
       
  1016  *       We therefore consider it an error if an il_operand is specified! This error will be caught elsewhere!
       
  1017  */
       
  1018 void *constant_folding_c::visit(  NOT_operator_c *symbol) {return handle_not(symbol, prev_il_instruction);}
       
  1019 
       
  1020 /* NOTE: Since we are only implementing a constant folding algorithm, and not a constant propagation algorithm,
       
  1021  *       the following IL instructions do not change/set the value of the il_operand!
       
  1022  */
       
  1023 void *constant_folding_c::visit(    S_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
       
  1024 void *constant_folding_c::visit(    R_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
       
  1025 
       
  1026 /* FB calls leave the value in the accumulator unchanged */
       
  1027 void *constant_folding_c::visit(   S1_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
       
  1028 void *constant_folding_c::visit(   R1_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
       
  1029 void *constant_folding_c::visit(  CLK_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
       
  1030 void *constant_folding_c::visit(   CU_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
       
  1031 void *constant_folding_c::visit(   CD_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
       
  1032 void *constant_folding_c::visit(   PV_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
       
  1033 void *constant_folding_c::visit(   IN_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
       
  1034 void *constant_folding_c::visit(   PT_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
       
  1035 
       
  1036 void *constant_folding_c::visit(  AND_operator_c *symbol) {return handle_and (symbol, prev_il_instruction, il_operand);}
       
  1037 void *constant_folding_c::visit(   OR_operator_c *symbol) {return handle_or  (symbol, prev_il_instruction, il_operand);}
       
  1038 void *constant_folding_c::visit(  XOR_operator_c *symbol) {return handle_xor (symbol, prev_il_instruction, il_operand);}
       
  1039 void *constant_folding_c::visit( ANDN_operator_c *symbol) {       handle_and (symbol, prev_il_instruction, il_operand); return handle_not(symbol, symbol);}
       
  1040 void *constant_folding_c::visit(  ORN_operator_c *symbol) {       handle_or  (symbol, prev_il_instruction, il_operand); return handle_not(symbol, symbol);}
       
  1041 void *constant_folding_c::visit( XORN_operator_c *symbol) {       handle_xor (symbol, prev_il_instruction, il_operand); return handle_not(symbol, symbol);}
       
  1042 
       
  1043 void *constant_folding_c::visit(  ADD_operator_c *symbol) {return handle_add (symbol, prev_il_instruction, il_operand);}
       
  1044 void *constant_folding_c::visit(  SUB_operator_c *symbol) {return handle_sub (symbol, prev_il_instruction, il_operand);}
       
  1045 void *constant_folding_c::visit(  MUL_operator_c *symbol) {return handle_mul (symbol, prev_il_instruction, il_operand);}
       
  1046 void *constant_folding_c::visit(  DIV_operator_c *symbol) {return handle_div (symbol, prev_il_instruction, il_operand);}
       
  1047 void *constant_folding_c::visit(  MOD_operator_c *symbol) {return handle_mod (symbol, prev_il_instruction, il_operand);}
       
  1048 
       
  1049 void *constant_folding_c::visit(   GT_operator_c *symbol) {       handle_cmp (symbol, prev_il_instruction, il_operand, > );}
       
  1050 void *constant_folding_c::visit(   GE_operator_c *symbol) {       handle_cmp (symbol, prev_il_instruction, il_operand, >=);}
       
  1051 void *constant_folding_c::visit(   EQ_operator_c *symbol) {       handle_cmp (symbol, prev_il_instruction, il_operand, ==);}
       
  1052 void *constant_folding_c::visit(   LT_operator_c *symbol) {       handle_cmp (symbol, prev_il_instruction, il_operand, < );}
       
  1053 void *constant_folding_c::visit(   LE_operator_c *symbol) {       handle_cmp (symbol, prev_il_instruction, il_operand, <=);}
       
  1054 void *constant_folding_c::visit(   NE_operator_c *symbol) {       handle_cmp (symbol, prev_il_instruction, il_operand, !=);}
       
  1055 
       
  1056 void *constant_folding_c::visit(  CAL_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
       
  1057 void *constant_folding_c::visit(  RET_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
       
  1058 void *constant_folding_c::visit(  JMP_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
       
  1059 void *constant_folding_c::visit( CALC_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
       
  1060 void *constant_folding_c::visit(CALCN_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
       
  1061 void *constant_folding_c::visit( RETC_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
       
  1062 void *constant_folding_c::visit(RETCN_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
       
  1063 void *constant_folding_c::visit( JMPC_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
       
  1064 void *constant_folding_c::visit(JMPCN_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
       
  1065 
       
  1066 
   679 
  1067 
   680 
  1068 
   681 /***************************************/
  1069 /***************************************/
   682 /* B.3 - Language ST (Structured Text) */
  1070 /* B.3 - Language ST (Structured Text) */
   683 /***************************************/
  1071 /***************************************/
   684 /***********************/
  1072 /***********************/
   685 /* B 3.1 - Expressions */
  1073 /* B 3.1 - Expressions */
   686 /***********************/
  1074 /***********************/
   687 void *constant_folding_c::visit(or_expression_c *symbol) {
  1075 void *constant_folding_c::visit(    or_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this); return handle_or (symbol, symbol->l_exp, symbol->r_exp);}
   688 	symbol->l_exp->accept(*this);
  1076 void *constant_folding_c::visit(   xor_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this); return handle_xor(symbol, symbol->l_exp, symbol->r_exp);}
   689 	symbol->r_exp->accept(*this);
  1077 void *constant_folding_c::visit(   and_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this); return handle_and(symbol, symbol->l_exp, symbol->r_exp);}
   690 	DO_BINARY_OPER(  bool, ||, bool);
  1078 
   691 	DO_BINARY_OPER(uint64, | , uint64);
  1079 void *constant_folding_c::visit(   equ_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this);        handle_cmp (symbol, symbol->l_exp, symbol->r_exp, ==);}
   692 	return NULL;
  1080 void *constant_folding_c::visit(notequ_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this);        handle_cmp (symbol, symbol->l_exp, symbol->r_exp, !=);}
   693 }
  1081 void *constant_folding_c::visit(    lt_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this);        handle_cmp (symbol, symbol->l_exp, symbol->r_exp, < );}
   694 
  1082 void *constant_folding_c::visit(    gt_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this);        handle_cmp (symbol, symbol->l_exp, symbol->r_exp, > );}
   695 
  1083 void *constant_folding_c::visit(    le_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this);        handle_cmp (symbol, symbol->l_exp, symbol->r_exp, <=);}
   696 void *constant_folding_c::visit(xor_expression_c *symbol) {
  1084 void *constant_folding_c::visit(    ge_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this);        handle_cmp (symbol, symbol->l_exp, symbol->r_exp, >=);}
   697 	symbol->l_exp->accept(*this);
  1085 
   698 	symbol->r_exp->accept(*this);
  1086 void *constant_folding_c::visit(   add_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this); return handle_add(symbol, symbol->l_exp, symbol->r_exp);}
   699 	DO_BINARY_OPER(  bool, ^, bool);
  1087 void *constant_folding_c::visit(   sub_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this); return handle_sub(symbol, symbol->l_exp, symbol->r_exp);}
   700 	DO_BINARY_OPER(uint64, ^, uint64);
  1088 void *constant_folding_c::visit(   mul_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this); return handle_mul(symbol, symbol->l_exp, symbol->r_exp);}
   701 	return NULL;
  1089 void *constant_folding_c::visit(   div_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this); return handle_div(symbol, symbol->l_exp, symbol->r_exp);}
   702 }
  1090 void *constant_folding_c::visit(   mod_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this); return handle_mod(symbol, symbol->l_exp, symbol->r_exp);}
   703 
  1091 void *constant_folding_c::visit( power_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this); return handle_pow(symbol, symbol->l_exp, symbol->r_exp);}
   704 
  1092 
   705 void *constant_folding_c::visit(and_expression_c *symbol) {
  1093 void *constant_folding_c::visit(   neg_expression_c *symbol) {symbol->  exp->accept(*this); return handle_neg(symbol, symbol->exp);}
   706 	symbol->l_exp->accept(*this);
  1094 void *constant_folding_c::visit(   not_expression_c *symbol) {symbol->  exp->accept(*this); return handle_not(symbol, symbol->exp);}
   707 	symbol->r_exp->accept(*this);
  1095 
   708 	DO_BINARY_OPER(  bool, &&, bool);
  1096 /* TODO: handle function invocations... */
   709 	DO_BINARY_OPER(uint64, & , uint64);
  1097 // void *fill_candidate_datatypes_c::visit(function_invocation_c *symbol) {}
   710 	return NULL;
       
   711 }
       
   712 
       
   713 
       
   714 void *constant_folding_c::visit(equ_expression_c *symbol) {
       
   715 	symbol->l_exp->accept(*this);
       
   716 	symbol->r_exp->accept(*this);
       
   717 	DO_BINARY_OPER(  bool, ==, bool);
       
   718 	DO_BINARY_OPER(uint64, ==, bool);
       
   719 	DO_BINARY_OPER( int64, ==, bool);
       
   720 	DO_BINARY_OPER(real64, ==, bool);
       
   721 	return NULL;
       
   722 }
       
   723 
       
   724 
       
   725 void *constant_folding_c::visit(notequ_expression_c *symbol) {
       
   726 	symbol->l_exp->accept(*this);
       
   727 	symbol->r_exp->accept(*this);
       
   728 	DO_BINARY_OPER(  bool, !=, bool);
       
   729 	DO_BINARY_OPER(uint64, !=, bool);
       
   730 	DO_BINARY_OPER( int64, !=, bool);
       
   731 	DO_BINARY_OPER(real64, !=, bool);
       
   732 	return NULL;
       
   733 }
       
   734 
       
   735 
       
   736 void *constant_folding_c::visit(lt_expression_c *symbol) {
       
   737 	symbol->l_exp->accept(*this);
       
   738 	symbol->r_exp->accept(*this);
       
   739 	DO_BINARY_OPER(  bool, <, bool);
       
   740 	DO_BINARY_OPER(uint64, <, bool);
       
   741 	DO_BINARY_OPER( int64, <, bool);
       
   742 	DO_BINARY_OPER(real64, <, bool);
       
   743 	return NULL;
       
   744 }
       
   745 
       
   746 
       
   747 void *constant_folding_c::visit(gt_expression_c *symbol) {
       
   748 	symbol->l_exp->accept(*this);
       
   749 	symbol->r_exp->accept(*this);
       
   750 	DO_BINARY_OPER(  bool, >, bool);
       
   751 	DO_BINARY_OPER(uint64, >, bool);
       
   752 	DO_BINARY_OPER( int64, >, bool);
       
   753 	DO_BINARY_OPER(real64, >, bool);
       
   754 	return NULL;
       
   755 }
       
   756 
       
   757 
       
   758 void *constant_folding_c::visit(le_expression_c *symbol) {
       
   759 	symbol->l_exp->accept(*this);
       
   760 	symbol->r_exp->accept(*this);
       
   761 	DO_BINARY_OPER(  bool, <=, bool);
       
   762 	DO_BINARY_OPER(uint64, <=, bool);
       
   763 	DO_BINARY_OPER( int64, <=, bool);
       
   764 	DO_BINARY_OPER(real64, <=, bool);
       
   765 	return NULL;
       
   766 }
       
   767 
       
   768 
       
   769 void *constant_folding_c::visit(ge_expression_c *symbol) {
       
   770 	symbol->l_exp->accept(*this);
       
   771 	symbol->r_exp->accept(*this);
       
   772 	DO_BINARY_OPER(  bool, >=, bool);
       
   773 	DO_BINARY_OPER(uint64, >=, bool);
       
   774 	DO_BINARY_OPER( int64, >=, bool);
       
   775 	DO_BINARY_OPER(real64, >=, bool);
       
   776 	return NULL;
       
   777 }
       
   778 
       
   779 
       
   780 void *constant_folding_c::visit(add_expression_c *symbol) {
       
   781 	symbol->l_exp->accept(*this);
       
   782 	symbol->r_exp->accept(*this);
       
   783 	DO_BINARY_OPER(uint64, +, uint64);   CHECK_OVERFLOW_uint64_SUM(symbol, symbol->l_exp, symbol->r_exp);
       
   784 	DO_BINARY_OPER( int64, +,  int64);   CHECK_OVERFLOW_int64_SUM (symbol, symbol->l_exp, symbol->r_exp);
       
   785 	DO_BINARY_OPER(real64, +, real64);   CHECK_OVERFLOW_real64    (symbol);
       
   786 	return NULL;
       
   787 }
       
   788 
       
   789 
       
   790 void *constant_folding_c::visit(sub_expression_c *symbol) {
       
   791 	symbol->l_exp->accept(*this);
       
   792 	symbol->r_exp->accept(*this);
       
   793 	DO_BINARY_OPER(uint64, -, uint64);   CHECK_OVERFLOW_uint64_SUB(symbol, symbol->l_exp, symbol->r_exp);
       
   794 	DO_BINARY_OPER( int64, -,  int64);   CHECK_OVERFLOW_int64_SUB (symbol, symbol->l_exp, symbol->r_exp);
       
   795 	DO_BINARY_OPER(real64, -, real64);   CHECK_OVERFLOW_real64    (symbol);
       
   796 	return NULL;
       
   797 }
       
   798 
       
   799 
       
   800 void *constant_folding_c::visit(mul_expression_c *symbol) {
       
   801 	symbol->l_exp->accept(*this);
       
   802 	symbol->r_exp->accept(*this);
       
   803 	DO_BINARY_OPER(uint64, *, uint64);   CHECK_OVERFLOW_uint64_MUL(symbol, symbol->l_exp, symbol->r_exp);
       
   804 	DO_BINARY_OPER( int64, *,  int64);   CHECK_OVERFLOW_int64_MUL (symbol, symbol->l_exp, symbol->r_exp);
       
   805 	DO_BINARY_OPER(real64, *, real64);   CHECK_OVERFLOW_real64    (symbol);
       
   806 	return NULL;
       
   807 }
       
   808 
       
   809 
       
   810 
       
   811 void *constant_folding_c::visit(div_expression_c *symbol) {
       
   812 	symbol->l_exp->accept(*this);
       
   813 	symbol->r_exp->accept(*this);
       
   814 	if (ISZERO_CVALUE(uint64, symbol->r_exp))  {NEW_CVALUE(uint64, symbol); SET_OVFLOW(uint64, symbol);} else {DO_BINARY_OPER(uint64, /, uint64); CHECK_OVERFLOW_uint64_DIV(symbol, symbol->l_exp, symbol->r_exp);};
       
   815 	if (ISZERO_CVALUE( int64, symbol->r_exp))  {NEW_CVALUE( int64, symbol); SET_OVFLOW( int64, symbol);} else {DO_BINARY_OPER( int64, /,  int64); CHECK_OVERFLOW_int64_DIV(symbol, symbol->l_exp, symbol->r_exp);};
       
   816 	if (ISZERO_CVALUE(real64, symbol->r_exp))  {NEW_CVALUE(real64, symbol); SET_OVFLOW(real64, symbol);} else {DO_BINARY_OPER(real64, /, real64); CHECK_OVERFLOW_real64(symbol);};
       
   817 	return NULL;
       
   818 }
       
   819 
       
   820 
       
   821 void *constant_folding_c::visit(mod_expression_c *symbol) {
       
   822 	symbol->l_exp->accept(*this);
       
   823 	symbol->r_exp->accept(*this);
       
   824 	/* IEC 61131-3 standard says IN1 MOD IN2 must be equivalent to
       
   825 	 *  IF (IN2 = 0) THEN OUT:=0 ; ELSE OUT:=IN1 - (IN1/IN2)*IN2 ; END_IF
       
   826 	 *
       
   827 	 * Note that, when IN1 = INT64_MIN, and IN2 = -1, an overflow occurs in the division,
       
   828 	 * so although the MOD operation should be OK, acording to the above definition, we actually have an overflow!!
       
   829 	 */
       
   830 	if (ISZERO_CVALUE(uint64, symbol->r_exp))  {NEW_CVALUE(uint64, symbol); SET_CVALUE(uint64, symbol, 0);} else {DO_BINARY_OPER(uint64, %, uint64); CHECK_OVERFLOW_uint64_MOD(symbol, symbol->l_exp, symbol->r_exp);};
       
   831 	if (ISZERO_CVALUE( int64, symbol->r_exp))  {NEW_CVALUE( int64, symbol); SET_CVALUE( int64, symbol, 0);} else {DO_BINARY_OPER( int64, %,  int64); CHECK_OVERFLOW_int64_MOD(symbol, symbol->l_exp, symbol->r_exp);};
       
   832 	return NULL;
       
   833 }
       
   834 
       
   835 
       
   836 void *constant_folding_c::visit(power_expression_c *symbol) {
       
   837 	symbol->l_exp->accept(*this);
       
   838 	symbol->r_exp->accept(*this);
       
   839 	/* NOTE: If the const_value in symbol->r_exp is within the limits of both int64 and uint64, then we do both operations.
       
   840 	 *       That is OK, as the result should be identicial (we do create an unnecessary CVALUE variable, but who cares?).
       
   841 	 *       If only one is valid, then that is the oper we will do!
       
   842 	 */
       
   843 	if (VALID_CVALUE(real64, symbol->l_exp) && VALID_CVALUE( int64, symbol->r_exp)) {
       
   844 		NEW_CVALUE(real64, symbol);
       
   845 		SET_CVALUE(real64, symbol, pow(GET_CVALUE(real64, symbol->l_exp), GET_CVALUE( int64, symbol->r_exp)));
       
   846 	}
       
   847 	if (VALID_CVALUE(real64, symbol->l_exp) && VALID_CVALUE(uint64, symbol->r_exp)) {
       
   848 		NEW_CVALUE(real64, symbol);
       
   849 		SET_CVALUE(real64, symbol, pow(GET_CVALUE(real64, symbol->l_exp), GET_CVALUE(uint64, symbol->r_exp)));
       
   850 	}
       
   851 	CHECK_OVERFLOW_real64(symbol);
       
   852 	return NULL;
       
   853 }
       
   854 
       
   855 
       
   856 void *constant_folding_c::visit(neg_expression_c *symbol) {
       
   857 	symbol->exp->accept(*this);
       
   858 	DO_UNARY_OPER( int64, -, symbol->exp);	CHECK_OVERFLOW_int64_NEG(symbol, symbol->exp);
       
   859 	DO_UNARY_OPER(real64, -, symbol->exp);	CHECK_OVERFLOW_real64(symbol);
       
   860 	return NULL;
       
   861 }
       
   862 
       
   863 
       
   864 
       
   865 void *constant_folding_c::visit(not_expression_c *symbol) {
       
   866 	symbol->exp->accept(*this);
       
   867 	DO_UNARY_OPER(  bool, !, symbol->exp);
       
   868 	DO_UNARY_OPER(uint64, ~, symbol->exp);
       
   869 	return NULL;
       
   870 }
       
   871 
       
   872