722 SET_CVALUE(real64, symbol, pow(GET_CVALUE(real64, oper1), GET_CVALUE(uint64, oper2))); |
723 SET_CVALUE(real64, symbol, pow(GET_CVALUE(real64, oper1), GET_CVALUE(uint64, oper2))); |
723 CHECK_OVERFLOW_real64(symbol); |
724 CHECK_OVERFLOW_real64(symbol); |
724 return NULL; |
725 return NULL; |
725 } |
726 } |
726 |
727 |
727 static constant_folding_c::map_values_t inner_left_join_values(constant_folding_c::map_values_t m1, constant_folding_c::map_values_t m2) { |
728 |
728 constant_folding_c::map_values_t::const_iterator itr; |
729 /***********************************************************************/ |
729 constant_folding_c::map_values_t ret; |
730 /***********************************************************************/ |
|
731 /***********************************************************************/ |
|
732 /*** Helper functions for handling IL instruction lists. ***/ |
|
733 /***********************************************************************/ |
|
734 /***********************************************************************/ |
|
735 /***********************************************************************/ |
|
736 |
|
737 |
|
738 /* 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! */ |
|
739 #define intersect_prev_CVALUE_(dtype, symbol) { \ |
|
740 symbol->const_value._##dtype = symbol->prev_il_instruction[0]->const_value._##dtype; \ |
|
741 for (unsigned int i = 1; i < symbol->prev_il_instruction.size(); i++) { \ |
|
742 if (!ISEQUAL_CVALUE(dtype, symbol, symbol->prev_il_instruction[i])) \ |
|
743 {SET_NONCONST(dtype, symbol); break;} \ |
|
744 } \ |
|
745 } |
|
746 |
|
747 static void intersect_prev_cvalues(il_instruction_c *symbol) { |
|
748 if (symbol->prev_il_instruction.empty()) |
|
749 return; |
|
750 intersect_prev_CVALUE_(real64, symbol); |
|
751 intersect_prev_CVALUE_(uint64, symbol); |
|
752 intersect_prev_CVALUE_( int64, symbol); |
|
753 intersect_prev_CVALUE_( bool, symbol); |
|
754 } |
|
755 |
|
756 |
|
757 |
|
758 /***********************************************************************/ |
|
759 /***********************************************************************/ |
|
760 /***********************************************************************/ |
|
761 /*** The constant_folding_c ***/ |
|
762 /***********************************************************************/ |
|
763 /***********************************************************************/ |
|
764 /***********************************************************************/ |
|
765 |
|
766 |
|
767 constant_folding_c::constant_folding_c(symbol_c *symbol) { |
|
768 error_count = 0; |
|
769 warning_found = false; |
|
770 current_display_error_level = 0; |
|
771 il_operand = NULL; |
|
772 prev_il_instruction = NULL; |
|
773 |
|
774 /* check whether the platform on which the compiler is being run implements IEC 559 floating point data types. */ |
|
775 symbol_c null_symbol; |
|
776 if (! (std::numeric_limits<real64_t>::is_iec559) ) |
|
777 STAGE3_WARNING(&null_symbol, &null_symbol, "The platform running the compiler does not implement IEC 60559 floating point numbers. " |
|
778 "Any error and/or warning messages related to overflow/underflow of the result of operations on REAL/LREAL literals " |
|
779 "(i.e. constant folding) may themselves be erroneous, although are most probably correct." |
|
780 "However, more likely is the possible existance of overflow/underflow errors that are not detected."); |
|
781 } |
|
782 |
|
783 |
|
784 constant_folding_c::~constant_folding_c(void) { |
|
785 } |
|
786 |
|
787 |
|
788 int constant_folding_c::get_error_count() { |
|
789 return error_count; |
|
790 } |
|
791 |
|
792 |
|
793 |
|
794 /*********************/ |
|
795 /* B 1.2 - Constants */ |
|
796 /*********************/ |
|
797 /******************************/ |
|
798 /* B 1.2.1 - Numeric Literals */ |
|
799 /******************************/ |
|
800 void *constant_folding_c::visit(real_c *symbol) { |
|
801 bool overflow; |
|
802 SET_CVALUE(real64, symbol, extract_real_value(symbol, &overflow)); |
|
803 if (overflow) SET_OVFLOW(real64, symbol); |
|
804 return NULL; |
|
805 } |
|
806 |
|
807 |
|
808 void *constant_folding_c::visit(integer_c *symbol) { |
|
809 bool overflow; |
|
810 SET_CVALUE( int64, symbol, extract_int64_value (symbol, &overflow)); |
|
811 if (overflow) SET_OVFLOW(int64, symbol); |
|
812 SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow)); |
|
813 if (overflow) SET_OVFLOW(uint64, symbol); |
|
814 return NULL; |
|
815 } |
|
816 |
|
817 |
|
818 void *constant_folding_c::visit(neg_real_c *symbol) { |
|
819 symbol->exp->accept(*this); |
|
820 DO_UNARY_OPER(real64, -, symbol->exp); CHECK_OVERFLOW_real64(symbol); |
|
821 if (IS_OVFLOW(real64, symbol->exp)) SET_OVFLOW(real64, symbol); |
|
822 return NULL; |
|
823 } |
|
824 |
|
825 |
|
826 |
|
827 /* | '-' integer {$$ = new neg_integer_c($2, locloc(@$));} */ |
|
828 void *constant_folding_c::visit(neg_integer_c *symbol) { |
|
829 symbol->exp->accept(*this); |
|
830 /* Note that due to syntax restrictions, the value of symbol->exp will always be positive. |
|
831 * However, the following code does not depend on that restriction. |
|
832 */ |
|
833 /* The remainder of the code (for example, data type checking) considers the neg_integer_c as a leaf of the |
|
834 * abstract syntax tree, and therefore simply ignores the values of neg_integer_c->exp. |
|
835 * For this reason only, and in only this situation, we must guarantee that any 'overflow' situation in |
|
836 * the cvalue of neg_integer_c->exp is also reflected back to this neg_integer_c symbol. |
|
837 * For the rest of the code we do NOT do this, as it would gurantee that a single overflow deep inside |
|
838 * an expression would imply that the expression itself would also be set to 'overflow' condition. |
|
839 * This in turn would then have the compiler produce a whole load of error messages where they are not wanted! |
|
840 */ |
|
841 DO_UNARY_OPER(uint64, -, symbol->exp); CHECK_OVERFLOW_uint64_NEG(symbol, symbol->exp); /* handle the uintv := -0 situation */ |
|
842 if (IS_OVFLOW(uint64, symbol->exp)) SET_OVFLOW(uint64, symbol); |
|
843 DO_UNARY_OPER( int64, -, symbol->exp); CHECK_OVERFLOW_int64_NEG (symbol, symbol->exp); |
|
844 if (IS_OVFLOW( int64, symbol->exp)) SET_OVFLOW( int64, symbol); |
|
845 /* NOTE 1: INT64_MIN = -(INT64_MAX + 1) ---> assuming two's complement representation!!! |
|
846 * NOTE 2: if the user happens to want INT_MIN, that value will first be parsed as a positive integer, before being negated here. |
|
847 * However, the positive value cannot be stored inside an int64! So, in this case, we will get the value from the uint64 cvalue. |
|
848 * |
|
849 * This same situation is usually considered an overflow (check handle_neg() function). However, here we have a special |
|
850 * situation. If we do not allow this, then the user would never the able to use the following code: |
|
851 * VAR v : LINT; END_VAR |
|
852 * v := -9223372036854775809 ; (* - |INT64_MIN| == INT64_MIN *) |
|
853 */ |
|
854 // if (INT64_MIN == -INT64_MAX - 1) // We do not really need to check that the platform uses two's complement |
|
855 if (VALID_CVALUE(uint64, symbol->exp) && (GET_CVALUE(uint64, symbol->exp) == (uint64_t)INT64_MAX+1)) { |
|
856 SET_CVALUE(int64, symbol, INT64_MIN); |
|
857 } |
|
858 return NULL; |
|
859 } |
|
860 |
|
861 |
|
862 void *constant_folding_c::visit(binary_integer_c *symbol) { |
|
863 bool overflow; |
|
864 SET_CVALUE( int64, symbol, extract_int64_value (symbol, &overflow)); |
|
865 if (overflow) SET_OVFLOW(int64, symbol); |
|
866 SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow)); |
|
867 if (overflow) SET_OVFLOW(uint64, symbol); |
|
868 return NULL; |
|
869 } |
|
870 |
|
871 |
|
872 void *constant_folding_c::visit(octal_integer_c *symbol) { |
|
873 bool overflow; |
|
874 SET_CVALUE( int64, symbol, extract_int64_value (symbol, &overflow)); |
|
875 if (overflow) SET_OVFLOW(int64, symbol); |
|
876 SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow)); |
|
877 if (overflow) SET_OVFLOW(uint64, symbol); |
|
878 return NULL; |
|
879 } |
|
880 |
|
881 |
|
882 void *constant_folding_c::visit(hex_integer_c *symbol) { |
|
883 bool overflow; |
|
884 SET_CVALUE( int64, symbol, extract_int64_value (symbol, &overflow)); |
|
885 if (overflow) SET_OVFLOW(int64, symbol); |
|
886 SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow)); |
|
887 if (overflow) SET_OVFLOW(uint64, symbol); |
|
888 return NULL; |
|
889 } |
|
890 |
|
891 |
|
892 /* |
|
893 integer_literal: |
|
894 integer_type_name '#' signed_integer {$$ = new integer_literal_c($1, $3, locloc(@$));} |
|
895 | integer_type_name '#' binary_integer {$$ = new integer_literal_c($1, $3, locloc(@$));} |
|
896 | integer_type_name '#' octal_integer {$$ = new integer_literal_c($1, $3, locloc(@$));} |
|
897 | integer_type_name '#' hex_integer {$$ = new integer_literal_c($1, $3, locloc(@$));} |
|
898 */ |
|
899 // SYM_REF2(integer_literal_c, type, value) |
|
900 void *constant_folding_c::visit(integer_literal_c *symbol) { |
|
901 symbol->value->accept(*this); |
|
902 DO_UNARY_OPER( int64, /* none */, symbol->value); |
|
903 DO_UNARY_OPER(uint64, /* none */, symbol->value); |
|
904 return NULL; |
|
905 } |
|
906 |
|
907 |
|
908 void *constant_folding_c::visit(real_literal_c *symbol) { |
|
909 symbol->value->accept(*this); |
|
910 DO_UNARY_OPER(real64, /* none */, symbol->value); |
|
911 return NULL; |
|
912 } |
|
913 |
|
914 |
|
915 void *constant_folding_c::visit(bit_string_literal_c *symbol) { |
|
916 return NULL; |
|
917 } |
|
918 |
|
919 |
|
920 void *constant_folding_c::visit(boolean_literal_c *symbol) { |
|
921 symbol->value->accept(*this); |
|
922 DO_UNARY_OPER(bool, /* none */, symbol->value); |
|
923 return NULL; |
|
924 } |
|
925 |
|
926 |
|
927 void *constant_folding_c::visit(boolean_true_c *symbol) { |
|
928 SET_CVALUE(bool, symbol, true); |
|
929 return NULL; |
|
930 } |
|
931 |
|
932 |
|
933 void *constant_folding_c::visit(boolean_false_c *symbol) { |
|
934 SET_CVALUE(bool, symbol, false); |
|
935 return NULL; |
|
936 } |
|
937 |
|
938 /************************/ |
|
939 /* B 1.2.3.1 - Duration */ |
|
940 /********* **************/ |
|
941 void *constant_folding_c::visit(fixed_point_c *symbol) { |
|
942 bool overflow; |
|
943 SET_CVALUE(real64, symbol, extract_real_value(symbol, &overflow)); |
|
944 if (overflow) SET_OVFLOW(real64, symbol); |
|
945 return NULL; |
|
946 } |
|
947 |
|
948 |
|
949 |
|
950 /****************************************/ |
|
951 /* B.2 - Language IL (Instruction List) */ |
|
952 /****************************************/ |
|
953 /***********************************/ |
|
954 /* B 2.1 Instructions and Operands */ |
|
955 /***********************************/ |
|
956 /* Not needed, since we inherit from iterator_visitor_c */ |
|
957 /*| instruction_list il_instruction */ |
|
958 // SYM_LIST(instruction_list_c) |
|
959 // void *constant_folding_c::visit(instruction_list_c *symbol) {} |
|
960 |
|
961 /* | label ':' [il_incomplete_instruction] eol_list */ |
|
962 // SYM_REF2(il_instruction_c, label, il_instruction) |
|
963 // void *visit(instruction_list_c *symbol); |
|
964 void *constant_folding_c::visit(il_instruction_c *symbol) { |
|
965 if (NULL == symbol->il_instruction) { |
|
966 /* This empty/null il_instruction does not change the value of the current/default IL variable. |
|
967 * So it inherits the candidate_datatypes from it's previous IL instructions! |
|
968 */ |
|
969 intersect_prev_cvalues(symbol); |
|
970 } else { |
|
971 il_instruction_c fake_prev_il_instruction = *symbol; |
|
972 intersect_prev_cvalues(&fake_prev_il_instruction); |
|
973 |
|
974 if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL; |
|
975 else prev_il_instruction = &fake_prev_il_instruction; |
|
976 symbol->il_instruction->accept(*this); |
|
977 prev_il_instruction = NULL; |
|
978 |
|
979 /* This object has (inherits) the same cvalues as the il_instruction */ |
|
980 symbol->const_value = symbol->il_instruction->const_value; |
|
981 } |
|
982 |
|
983 return NULL; |
|
984 } |
|
985 |
|
986 |
|
987 void *constant_folding_c::visit(il_simple_operation_c *symbol) { |
|
988 /* determine the cvalue of the operand */ |
|
989 if (NULL != symbol->il_operand) { |
|
990 symbol->il_operand->accept(*this); |
|
991 } |
|
992 /* determine the cvalue resulting from executing the il_operator... */ |
|
993 il_operand = symbol->il_operand; |
|
994 symbol->il_simple_operator->accept(*this); |
|
995 il_operand = NULL; |
|
996 /* This object has (inherits) the same cvalues as the il_instruction */ |
|
997 symbol->const_value = symbol->il_simple_operator->const_value; |
|
998 return NULL; |
|
999 } |
|
1000 |
|
1001 |
|
1002 /* TODO: handle function invocations... */ |
|
1003 /* | function_name [il_operand_list] */ |
|
1004 /* NOTE: The parameters 'called_function_declaration' and 'extensible_param_count' are used to pass data between the stage 3 and stage 4. */ |
|
1005 // SYM_REF2(il_function_call_c, function_name, il_operand_list, symbol_c *called_function_declaration; int extensible_param_count;) |
|
1006 // void *constant_folding_c::visit(il_function_call_c *symbol) {} |
|
1007 |
|
1008 |
|
1009 /* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */ |
|
1010 // SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list); |
|
1011 void *constant_folding_c::visit(il_expression_c *symbol) { |
|
1012 symbol_c *prev_il_instruction_backup = prev_il_instruction; |
|
1013 |
|
1014 /* Stage2 will insert an artificial (and equivalent) LD <il_operand> to the simple_instr_list if necessary. We can therefore ignore the 'il_operand' entry! */ |
|
1015 // if (NULL != symbol->il_operand) |
|
1016 // symbol->il_operand->accept(*this); |
|
1017 |
|
1018 if(symbol->simple_instr_list != NULL) |
|
1019 symbol->simple_instr_list->accept(*this); |
|
1020 |
|
1021 /* Now do the operation, */ |
|
1022 il_operand = symbol->simple_instr_list; |
|
1023 prev_il_instruction = prev_il_instruction_backup; |
|
1024 symbol->il_expr_operator->accept(*this); |
|
1025 il_operand = NULL; |
|
1026 |
|
1027 /* This object has (inherits) the same cvalues as the il_instruction */ |
|
1028 symbol->const_value = symbol->il_expr_operator->const_value; |
|
1029 |
|
1030 /* Since stage2 will insert an artificial (and equivalent) LD <il_operand> to the simple_instr_list when an 'il_operand' exists, we know |
|
1031 * that if (symbol->il_operand != NULL), then the first IL instruction in the simple_instr_list will be the equivalent and artificial |
|
1032 * 'LD <il_operand>' IL instruction. |
|
1033 * Just to be cosistent, we will copy the constant info back into the il_operand, even though this should not be necessary! |
|
1034 */ |
|
1035 if ((NULL != symbol->il_operand) && ((NULL == symbol->simple_instr_list) || (0 == ((list_c *)symbol->simple_instr_list)->n))) ERROR; // stage2 is not behaving as we expect it to! |
|
1036 if (NULL != symbol->il_operand) |
|
1037 symbol->il_operand->const_value = ((list_c *)symbol->simple_instr_list)->elements[0]->const_value; |
|
1038 |
|
1039 return NULL; |
|
1040 } |
|
1041 |
|
1042 |
|
1043 |
|
1044 void *constant_folding_c::visit(il_jump_operation_c *symbol) { |
|
1045 /* recursive call to fill const values... */ |
|
1046 il_operand = NULL; |
|
1047 symbol->il_jump_operator->accept(*this); |
|
1048 il_operand = NULL; |
|
1049 /* This object has (inherits) the same cvalues as the il_jump_operator */ |
|
1050 symbol->const_value = symbol->il_jump_operator->const_value; |
|
1051 return NULL; |
|
1052 } |
|
1053 |
|
1054 |
|
1055 |
|
1056 /* FB calls leave the value in the accumulator unchanged */ |
|
1057 /* il_call_operator prev_declared_fb_name |
|
1058 * | il_call_operator prev_declared_fb_name '(' ')' |
|
1059 * | il_call_operator prev_declared_fb_name '(' eol_list ')' |
|
1060 * | il_call_operator prev_declared_fb_name '(' il_operand_list ')' |
|
1061 * | il_call_operator prev_declared_fb_name '(' eol_list il_param_list ')' |
|
1062 */ |
|
1063 /* 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 */ |
|
1064 // SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list, symbol_c *called_fb_declaration) |
|
1065 void *constant_folding_c::visit(il_fb_call_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1066 |
|
1067 |
|
1068 /* TODO: handle function invocations... */ |
|
1069 /* | function_name '(' eol_list [il_param_list] ')' */ |
|
1070 /* NOTE: The parameter 'called_function_declaration' is used to pass data between the stage 3 and stage 4. */ |
|
1071 // SYM_REF2(il_formal_funct_call_c, function_name, il_param_list, symbol_c *called_function_declaration; int extensible_param_count;) |
|
1072 // void *constant_folding_c::visit(il_formal_funct_call_c *symbol) {return NULL;} |
|
1073 |
|
1074 |
|
1075 |
|
1076 /* Not needed, since we inherit from iterator_visitor_c */ |
|
1077 // void *constant_folding_c::visit(il_operand_list_c *symbol); |
|
1078 |
|
1079 |
|
1080 |
|
1081 /* | simple_instr_list il_simple_instruction */ |
|
1082 /* This object is referenced by il_expression_c objects */ |
|
1083 void *constant_folding_c::visit(simple_instr_list_c *symbol) { |
|
1084 if (symbol->n <= 0) |
|
1085 return NULL; /* List is empty! Nothing to do. */ |
|
1086 |
|
1087 for(int i = 0; i < symbol->n; i++) |
|
1088 symbol->elements[i]->accept(*this); |
|
1089 |
|
1090 /* This object has (inherits) the same cvalues as the il_jump_operator */ |
|
1091 symbol->const_value = symbol->elements[symbol->n-1]->const_value; |
|
1092 return NULL; |
|
1093 } |
|
1094 |
|
1095 |
|
1096 |
|
1097 // SYM_REF1(il_simple_instruction_c, il_simple_instruction, symbol_c *prev_il_instruction;) |
|
1098 void *constant_folding_c::visit(il_simple_instruction_c *symbol) { |
|
1099 if (symbol->prev_il_instruction.size() > 1) ERROR; /* There should be no labeled insructions inside an IL expression! */ |
|
1100 if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL; |
|
1101 else prev_il_instruction = symbol->prev_il_instruction[0]; |
|
1102 symbol->il_simple_instruction->accept(*this); |
|
1103 prev_il_instruction = NULL; |
|
1104 |
|
1105 /* This object has (inherits) the same cvalues as the il_jump_operator */ |
|
1106 symbol->const_value = symbol->il_simple_instruction->const_value; |
|
1107 return NULL; |
|
1108 } |
|
1109 |
|
1110 |
|
1111 /* |
|
1112 void *visit(il_param_list_c *symbol); |
|
1113 void *visit(il_param_assignment_c *symbol); |
|
1114 void *visit(il_param_out_assignment_c *symbol); |
|
1115 */ |
|
1116 |
|
1117 |
|
1118 /*******************/ |
|
1119 /* B 2.2 Operators */ |
|
1120 /*******************/ |
|
1121 void *constant_folding_c::visit( LD_operator_c *symbol) {return handle_move(symbol, il_operand);} |
|
1122 void *constant_folding_c::visit( LDN_operator_c *symbol) {return handle_not (symbol, il_operand);} |
|
1123 |
|
1124 /* NOTE: we are implementing a constant folding algorithm, not a constant propagation algorithm. |
|
1125 * For the constant propagation algorithm, the correct implementation of ST(N)_operator_c would be... |
|
1126 */ |
|
1127 //void *constant_folding_c::visit( ST_operator_c *symbol) {return handle_move(il_operand, symbol);} |
|
1128 //void *constant_folding_c::visit( STN_operator_c *symbol) {return handle_not (il_operand, symbol);} |
|
1129 void *constant_folding_c::visit( ST_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1130 void *constant_folding_c::visit( STN_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1131 |
|
1132 /* NOTE: the standard allows syntax in which the NOT operator is followed by an optional <il_operand> |
|
1133 * NOT [<il_operand>] |
|
1134 * However, it does not define the semantic of the NOT operation when the <il_operand> is specified. |
|
1135 * We therefore consider it an error if an il_operand is specified! This error will be caught elsewhere! |
|
1136 */ |
|
1137 void *constant_folding_c::visit( NOT_operator_c *symbol) {return handle_not(symbol, prev_il_instruction);} |
|
1138 |
|
1139 /* NOTE: Since we are only implementing a constant folding algorithm, and not a constant propagation algorithm, |
|
1140 * the following IL instructions do not change/set the value of the il_operand! |
|
1141 */ |
|
1142 void *constant_folding_c::visit( S_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1143 void *constant_folding_c::visit( R_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1144 |
|
1145 /* FB calls leave the value in the accumulator unchanged */ |
|
1146 void *constant_folding_c::visit( S1_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1147 void *constant_folding_c::visit( R1_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1148 void *constant_folding_c::visit( CLK_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1149 void *constant_folding_c::visit( CU_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1150 void *constant_folding_c::visit( CD_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1151 void *constant_folding_c::visit( PV_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1152 void *constant_folding_c::visit( IN_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1153 void *constant_folding_c::visit( PT_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1154 |
|
1155 void *constant_folding_c::visit( AND_operator_c *symbol) {return handle_and (symbol, prev_il_instruction, il_operand);} |
|
1156 void *constant_folding_c::visit( OR_operator_c *symbol) {return handle_or (symbol, prev_il_instruction, il_operand);} |
|
1157 void *constant_folding_c::visit( XOR_operator_c *symbol) {return handle_xor (symbol, prev_il_instruction, il_operand);} |
|
1158 void *constant_folding_c::visit( ANDN_operator_c *symbol) { handle_and (symbol, prev_il_instruction, il_operand); return handle_not(symbol, symbol);} |
|
1159 void *constant_folding_c::visit( ORN_operator_c *symbol) { handle_or (symbol, prev_il_instruction, il_operand); return handle_not(symbol, symbol);} |
|
1160 void *constant_folding_c::visit( XORN_operator_c *symbol) { handle_xor (symbol, prev_il_instruction, il_operand); return handle_not(symbol, symbol);} |
|
1161 |
|
1162 void *constant_folding_c::visit( ADD_operator_c *symbol) {return handle_add (symbol, prev_il_instruction, il_operand);} |
|
1163 void *constant_folding_c::visit( SUB_operator_c *symbol) {return handle_sub (symbol, prev_il_instruction, il_operand);} |
|
1164 void *constant_folding_c::visit( MUL_operator_c *symbol) {return handle_mul (symbol, prev_il_instruction, il_operand);} |
|
1165 void *constant_folding_c::visit( DIV_operator_c *symbol) {return handle_div (symbol, prev_il_instruction, il_operand);} |
|
1166 void *constant_folding_c::visit( MOD_operator_c *symbol) {return handle_mod (symbol, prev_il_instruction, il_operand);} |
|
1167 |
|
1168 void *constant_folding_c::visit( GT_operator_c *symbol) { handle_cmp (symbol, prev_il_instruction, il_operand, > );} |
|
1169 void *constant_folding_c::visit( GE_operator_c *symbol) { handle_cmp (symbol, prev_il_instruction, il_operand, >=);} |
|
1170 void *constant_folding_c::visit( EQ_operator_c *symbol) { handle_cmp (symbol, prev_il_instruction, il_operand, ==);} |
|
1171 void *constant_folding_c::visit( LT_operator_c *symbol) { handle_cmp (symbol, prev_il_instruction, il_operand, < );} |
|
1172 void *constant_folding_c::visit( LE_operator_c *symbol) { handle_cmp (symbol, prev_il_instruction, il_operand, <=);} |
|
1173 void *constant_folding_c::visit( NE_operator_c *symbol) { handle_cmp (symbol, prev_il_instruction, il_operand, !=);} |
|
1174 |
|
1175 void *constant_folding_c::visit( CAL_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1176 void *constant_folding_c::visit( RET_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1177 void *constant_folding_c::visit( JMP_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1178 void *constant_folding_c::visit( CALC_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1179 void *constant_folding_c::visit(CALCN_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1180 void *constant_folding_c::visit( RETC_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1181 void *constant_folding_c::visit(RETCN_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1182 void *constant_folding_c::visit( JMPC_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1183 void *constant_folding_c::visit(JMPCN_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1184 |
|
1185 |
|
1186 |
|
1187 |
|
1188 /***************************************/ |
|
1189 /* B.3 - Language ST (Structured Text) */ |
|
1190 /***************************************/ |
|
1191 /***********************/ |
|
1192 /* B 3.1 - Expressions */ |
|
1193 /***********************/ |
|
1194 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);} |
|
1195 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);} |
|
1196 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);} |
|
1197 |
|
1198 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, ==);} |
|
1199 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, !=);} |
|
1200 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, < );} |
|
1201 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, > );} |
|
1202 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, <=);} |
|
1203 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, >=);} |
|
1204 |
|
1205 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);} |
|
1206 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);} |
|
1207 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);} |
|
1208 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);} |
|
1209 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);} |
|
1210 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);} |
|
1211 |
|
1212 void *constant_folding_c::visit( neg_expression_c *symbol) {symbol-> exp->accept(*this); return handle_neg(symbol, symbol->exp);} |
|
1213 void *constant_folding_c::visit( not_expression_c *symbol) {symbol-> exp->accept(*this); return handle_not(symbol, symbol->exp);} |
|
1214 |
|
1215 |
|
1216 |
|
1217 |
|
1218 |
|
1219 |
|
1220 |
|
1221 |
|
1222 |
|
1223 |
|
1224 |
|
1225 /***********************************************************************/ |
|
1226 /***********************************************************************/ |
|
1227 /***********************************************************************/ |
|
1228 /*** The constant_propagation_c ***/ |
|
1229 /***********************************************************************/ |
|
1230 /***********************************************************************/ |
|
1231 /***********************************************************************/ |
|
1232 |
|
1233 |
|
1234 constant_propagation_c::constant_propagation_c(symbol_c *symbol) |
|
1235 : constant_folding_c(symbol) { |
|
1236 current_resource = NULL; |
|
1237 current_configuration = NULL; |
|
1238 fixed_init_value_ = false; |
|
1239 function_pou_ = false; |
|
1240 } |
|
1241 |
|
1242 |
|
1243 constant_propagation_c::~constant_propagation_c(void) {} |
|
1244 |
|
1245 |
|
1246 static constant_propagation_c::map_values_t inner_left_join_values(constant_propagation_c::map_values_t m1, constant_propagation_c::map_values_t m2) { |
|
1247 constant_propagation_c::map_values_t::const_iterator itr; |
|
1248 constant_propagation_c::map_values_t ret; |
730 |
1249 |
731 itr = m1.begin(); |
1250 itr = m1.begin(); |
732 for ( ; itr != m1.end(); ++itr) { |
1251 for ( ; itr != m1.end(); ++itr) { |
733 std::string name = itr->first; |
1252 std::string name = itr->first; |
734 const_value_c value; |
1253 const_value_c value; |
939 } |
1372 } |
940 |
1373 |
941 return NULL; |
1374 return NULL; |
942 } |
1375 } |
943 |
1376 |
944 /*********************/ |
|
945 /* B 1.2 - Constants */ |
|
946 /*********************/ |
|
947 /******************************/ |
|
948 /* B 1.2.1 - Numeric Literals */ |
|
949 /******************************/ |
|
950 void *constant_folding_c::visit(real_c *symbol) { |
|
951 bool overflow; |
|
952 SET_CVALUE(real64, symbol, extract_real_value(symbol, &overflow)); |
|
953 if (overflow) SET_OVFLOW(real64, symbol); |
|
954 return NULL; |
|
955 } |
|
956 |
|
957 |
|
958 void *constant_folding_c::visit(integer_c *symbol) { |
|
959 bool overflow; |
|
960 SET_CVALUE( int64, symbol, extract_int64_value (symbol, &overflow)); |
|
961 if (overflow) SET_OVFLOW(int64, symbol); |
|
962 SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow)); |
|
963 if (overflow) SET_OVFLOW(uint64, symbol); |
|
964 return NULL; |
|
965 } |
|
966 |
|
967 |
|
968 void *constant_folding_c::visit(neg_real_c *symbol) { |
|
969 symbol->exp->accept(*this); |
|
970 DO_UNARY_OPER(real64, -, symbol->exp); CHECK_OVERFLOW_real64(symbol); |
|
971 if (IS_OVFLOW(real64, symbol->exp)) SET_OVFLOW(real64, symbol); |
|
972 return NULL; |
|
973 } |
|
974 |
|
975 |
|
976 |
|
977 /* | '-' integer {$$ = new neg_integer_c($2, locloc(@$));} */ |
|
978 void *constant_folding_c::visit(neg_integer_c *symbol) { |
|
979 symbol->exp->accept(*this); |
|
980 /* Note that due to syntax restrictions, the value of symbol->exp will always be positive. |
|
981 * However, the following code does not depend on that restriction. |
|
982 */ |
|
983 /* The remainder of the code (for example, data type checking) considers the neg_integer_c as a leaf of the |
|
984 * abstract syntax tree, and therefore simply ignores the values of neg_integer_c->exp. |
|
985 * For this reason only, and in only this situation, we must guarantee that any 'overflow' situation in |
|
986 * the cvalue of neg_integer_c->exp is also reflected back to this neg_integer_c symbol. |
|
987 * For the rest of the code we do NOT do this, as it would gurantee that a single overflow deep inside |
|
988 * an expression would imply that the expression itself would also be set to 'overflow' condition. |
|
989 * This in turn would then have the compiler produce a whole load of error messages where they are not wanted! |
|
990 */ |
|
991 DO_UNARY_OPER(uint64, -, symbol->exp); CHECK_OVERFLOW_uint64_NEG(symbol, symbol->exp); /* handle the uintv := -0 situation */ |
|
992 if (IS_OVFLOW(uint64, symbol->exp)) SET_OVFLOW(uint64, symbol); |
|
993 DO_UNARY_OPER( int64, -, symbol->exp); CHECK_OVERFLOW_int64_NEG (symbol, symbol->exp); |
|
994 if (IS_OVFLOW( int64, symbol->exp)) SET_OVFLOW( int64, symbol); |
|
995 /* NOTE 1: INT64_MIN = -(INT64_MAX + 1) ---> assuming two's complement representation!!! |
|
996 * NOTE 2: if the user happens to want INT_MIN, that value will first be parsed as a positive integer, before being negated here. |
|
997 * However, the positive value cannot be stored inside an int64! So, in this case, we will get the value from the uint64 cvalue. |
|
998 * |
|
999 * This same situation is usually considered an overflow (check handle_neg() function). However, here we have a special |
|
1000 * situation. If we do not allow this, then the user would never the able to use the following code: |
|
1001 * VAR v : LINT; END_VAR |
|
1002 * v := -9223372036854775809 ; (* - |INT64_MIN| == INT64_MIN *) |
|
1003 */ |
|
1004 // if (INT64_MIN == -INT64_MAX - 1) // We do not really need to check that the platform uses two's complement |
|
1005 if (VALID_CVALUE(uint64, symbol->exp) && (GET_CVALUE(uint64, symbol->exp) == (uint64_t)INT64_MAX+1)) { |
|
1006 SET_CVALUE(int64, symbol, INT64_MIN); |
|
1007 } |
|
1008 return NULL; |
|
1009 } |
|
1010 |
|
1011 |
|
1012 void *constant_folding_c::visit(binary_integer_c *symbol) { |
|
1013 bool overflow; |
|
1014 SET_CVALUE( int64, symbol, extract_int64_value (symbol, &overflow)); |
|
1015 if (overflow) SET_OVFLOW(int64, symbol); |
|
1016 SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow)); |
|
1017 if (overflow) SET_OVFLOW(uint64, symbol); |
|
1018 return NULL; |
|
1019 } |
|
1020 |
|
1021 |
|
1022 void *constant_folding_c::visit(octal_integer_c *symbol) { |
|
1023 bool overflow; |
|
1024 SET_CVALUE( int64, symbol, extract_int64_value (symbol, &overflow)); |
|
1025 if (overflow) SET_OVFLOW(int64, symbol); |
|
1026 SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow)); |
|
1027 if (overflow) SET_OVFLOW(uint64, symbol); |
|
1028 return NULL; |
|
1029 } |
|
1030 |
|
1031 |
|
1032 void *constant_folding_c::visit(hex_integer_c *symbol) { |
|
1033 bool overflow; |
|
1034 SET_CVALUE( int64, symbol, extract_int64_value (symbol, &overflow)); |
|
1035 if (overflow) SET_OVFLOW(int64, symbol); |
|
1036 SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow)); |
|
1037 if (overflow) SET_OVFLOW(uint64, symbol); |
|
1038 return NULL; |
|
1039 } |
|
1040 |
|
1041 |
|
1042 /* |
|
1043 integer_literal: |
|
1044 integer_type_name '#' signed_integer {$$ = new integer_literal_c($1, $3, locloc(@$));} |
|
1045 | integer_type_name '#' binary_integer {$$ = new integer_literal_c($1, $3, locloc(@$));} |
|
1046 | integer_type_name '#' octal_integer {$$ = new integer_literal_c($1, $3, locloc(@$));} |
|
1047 | integer_type_name '#' hex_integer {$$ = new integer_literal_c($1, $3, locloc(@$));} |
|
1048 */ |
|
1049 // SYM_REF2(integer_literal_c, type, value) |
|
1050 void *constant_folding_c::visit(integer_literal_c *symbol) { |
|
1051 symbol->value->accept(*this); |
|
1052 DO_UNARY_OPER( int64, /* none */, symbol->value); |
|
1053 DO_UNARY_OPER(uint64, /* none */, symbol->value); |
|
1054 return NULL; |
|
1055 } |
|
1056 |
|
1057 |
|
1058 void *constant_folding_c::visit(real_literal_c *symbol) { |
|
1059 symbol->value->accept(*this); |
|
1060 DO_UNARY_OPER(real64, /* none */, symbol->value); |
|
1061 return NULL; |
|
1062 } |
|
1063 |
|
1064 |
|
1065 void *constant_folding_c::visit(bit_string_literal_c *symbol) { |
|
1066 return NULL; |
|
1067 } |
|
1068 |
|
1069 |
|
1070 void *constant_folding_c::visit(boolean_literal_c *symbol) { |
|
1071 symbol->value->accept(*this); |
|
1072 DO_UNARY_OPER(bool, /* none */, symbol->value); |
|
1073 return NULL; |
|
1074 } |
|
1075 |
|
1076 |
|
1077 void *constant_folding_c::visit(boolean_true_c *symbol) { |
|
1078 SET_CVALUE(bool, symbol, true); |
|
1079 return NULL; |
|
1080 } |
|
1081 |
|
1082 |
|
1083 void *constant_folding_c::visit(boolean_false_c *symbol) { |
|
1084 SET_CVALUE(bool, symbol, false); |
|
1085 return NULL; |
|
1086 } |
|
1087 |
|
1088 /************************/ |
|
1089 /* B 1.2.3.1 - Duration */ |
|
1090 /********* **************/ |
|
1091 void *constant_folding_c::visit(fixed_point_c *symbol) { |
|
1092 bool overflow; |
|
1093 SET_CVALUE(real64, symbol, extract_real_value(symbol, &overflow)); |
|
1094 if (overflow) SET_OVFLOW(real64, symbol); |
|
1095 return NULL; |
|
1096 } |
|
1097 |
1377 |
1098 /*********************/ |
1378 /*********************/ |
1099 /* B 1.4 - Variables */ |
1379 /* B 1.4 - Variables */ |
1100 /*********************/ |
1380 /*********************/ |
1101 #if DO_CONSTANT_PROPAGATION__ |
1381 #if DO_CONSTANT_PROPAGATION__ |
1102 void *constant_folding_c::visit(symbolic_variable_c *symbol) { |
1382 void *constant_propagation_c::visit(symbolic_variable_c *symbol) { |
1103 std::string varName = get_var_name_c::get_name(symbol->var_name)->value; |
1383 std::string varName = get_var_name_c::get_name(symbol->var_name)->value; |
1104 if (values.count(varName) > 0) |
1384 if (values.count(varName) > 0) |
1105 symbol->const_value = values[varName]; |
1385 symbol->const_value = values[varName]; |
1106 return NULL; |
1386 return NULL; |
1107 } |
1387 } |
1108 #endif // DO_CONSTANT_PROPAGATION__ |
1388 #endif // DO_CONSTANT_PROPAGATION__ |
1109 |
1389 |
1110 void *constant_folding_c::visit(symbolic_constant_c *symbol) { |
1390 void *constant_propagation_c::visit(symbolic_constant_c *symbol) { |
1111 std::string varName = get_var_name_c::get_name(symbol->var_name)->value; |
1391 std::string varName = get_var_name_c::get_name(symbol->var_name)->value; |
1112 if (values.count(varName) > 0) |
1392 if (values.count(varName) > 0) |
1113 symbol->const_value = values[varName]; |
1393 symbol->const_value = values[varName]; |
1114 return NULL; |
1394 return NULL; |
1115 } |
1395 } |
1608 // SYM_REF2(fb_initialization_c, function_block_type_name, structure_initialization) |
1888 // SYM_REF2(fb_initialization_c, function_block_type_name, structure_initialization) |
1609 |
1889 |
1610 |
1890 |
1611 |
1891 |
1612 |
1892 |
1613 /****************************************/ |
|
1614 /* B.2 - Language IL (Instruction List) */ |
|
1615 /****************************************/ |
|
1616 /***********************************/ |
|
1617 /* B 2.1 Instructions and Operands */ |
|
1618 /***********************************/ |
|
1619 /* Not needed, since we inherit from iterator_visitor_c */ |
|
1620 /*| instruction_list il_instruction */ |
|
1621 // SYM_LIST(instruction_list_c) |
|
1622 // void *constant_folding_c::visit(instruction_list_c *symbol) {} |
|
1623 |
|
1624 /* | label ':' [il_incomplete_instruction] eol_list */ |
|
1625 // SYM_REF2(il_instruction_c, label, il_instruction) |
|
1626 // void *visit(instruction_list_c *symbol); |
|
1627 void *constant_folding_c::visit(il_instruction_c *symbol) { |
|
1628 if (NULL == symbol->il_instruction) { |
|
1629 /* This empty/null il_instruction does not change the value of the current/default IL variable. |
|
1630 * So it inherits the candidate_datatypes from it's previous IL instructions! |
|
1631 */ |
|
1632 intersect_prev_cvalues(symbol); |
|
1633 } else { |
|
1634 il_instruction_c fake_prev_il_instruction = *symbol; |
|
1635 intersect_prev_cvalues(&fake_prev_il_instruction); |
|
1636 |
|
1637 if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL; |
|
1638 else prev_il_instruction = &fake_prev_il_instruction; |
|
1639 symbol->il_instruction->accept(*this); |
|
1640 prev_il_instruction = NULL; |
|
1641 |
|
1642 /* This object has (inherits) the same cvalues as the il_instruction */ |
|
1643 symbol->const_value = symbol->il_instruction->const_value; |
|
1644 } |
|
1645 |
|
1646 return NULL; |
|
1647 } |
|
1648 |
|
1649 |
|
1650 void *constant_folding_c::visit(il_simple_operation_c *symbol) { |
|
1651 /* determine the cvalue of the operand */ |
|
1652 if (NULL != symbol->il_operand) { |
|
1653 symbol->il_operand->accept(*this); |
|
1654 } |
|
1655 /* determine the cvalue resulting from executing the il_operator... */ |
|
1656 il_operand = symbol->il_operand; |
|
1657 symbol->il_simple_operator->accept(*this); |
|
1658 il_operand = NULL; |
|
1659 /* This object has (inherits) the same cvalues as the il_instruction */ |
|
1660 symbol->const_value = symbol->il_simple_operator->const_value; |
|
1661 return NULL; |
|
1662 } |
|
1663 |
|
1664 |
|
1665 /* TODO: handle function invocations... */ |
|
1666 /* | function_name [il_operand_list] */ |
|
1667 /* NOTE: The parameters 'called_function_declaration' and 'extensible_param_count' are used to pass data between the stage 3 and stage 4. */ |
|
1668 // SYM_REF2(il_function_call_c, function_name, il_operand_list, symbol_c *called_function_declaration; int extensible_param_count;) |
|
1669 // void *constant_folding_c::visit(il_function_call_c *symbol) {} |
|
1670 |
|
1671 |
|
1672 /* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */ |
|
1673 // SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list); |
|
1674 void *constant_folding_c::visit(il_expression_c *symbol) { |
|
1675 symbol_c *prev_il_instruction_backup = prev_il_instruction; |
|
1676 |
|
1677 /* Stage2 will insert an artificial (and equivalent) LD <il_operand> to the simple_instr_list if necessary. We can therefore ignore the 'il_operand' entry! */ |
|
1678 // if (NULL != symbol->il_operand) |
|
1679 // symbol->il_operand->accept(*this); |
|
1680 |
|
1681 if(symbol->simple_instr_list != NULL) |
|
1682 symbol->simple_instr_list->accept(*this); |
|
1683 |
|
1684 /* Now do the operation, */ |
|
1685 il_operand = symbol->simple_instr_list; |
|
1686 prev_il_instruction = prev_il_instruction_backup; |
|
1687 symbol->il_expr_operator->accept(*this); |
|
1688 il_operand = NULL; |
|
1689 |
|
1690 /* This object has (inherits) the same cvalues as the il_instruction */ |
|
1691 symbol->const_value = symbol->il_expr_operator->const_value; |
|
1692 |
|
1693 /* Since stage2 will insert an artificial (and equivalent) LD <il_operand> to the simple_instr_list when an 'il_operand' exists, we know |
|
1694 * that if (symbol->il_operand != NULL), then the first IL instruction in the simple_instr_list will be the equivalent and artificial |
|
1695 * 'LD <il_operand>' IL instruction. |
|
1696 * Just to be cosistent, we will copy the constant info back into the il_operand, even though this should not be necessary! |
|
1697 */ |
|
1698 if ((NULL != symbol->il_operand) && ((NULL == symbol->simple_instr_list) || (0 == ((list_c *)symbol->simple_instr_list)->n))) ERROR; // stage2 is not behaving as we expect it to! |
|
1699 if (NULL != symbol->il_operand) |
|
1700 symbol->il_operand->const_value = ((list_c *)symbol->simple_instr_list)->elements[0]->const_value; |
|
1701 |
|
1702 return NULL; |
|
1703 } |
|
1704 |
|
1705 |
|
1706 |
|
1707 void *constant_folding_c::visit(il_jump_operation_c *symbol) { |
|
1708 /* recursive call to fill const values... */ |
|
1709 il_operand = NULL; |
|
1710 symbol->il_jump_operator->accept(*this); |
|
1711 il_operand = NULL; |
|
1712 /* This object has (inherits) the same cvalues as the il_jump_operator */ |
|
1713 symbol->const_value = symbol->il_jump_operator->const_value; |
|
1714 return NULL; |
|
1715 } |
|
1716 |
|
1717 |
|
1718 |
|
1719 /* FB calls leave the value in the accumulator unchanged */ |
|
1720 /* il_call_operator prev_declared_fb_name |
|
1721 * | il_call_operator prev_declared_fb_name '(' ')' |
|
1722 * | il_call_operator prev_declared_fb_name '(' eol_list ')' |
|
1723 * | il_call_operator prev_declared_fb_name '(' il_operand_list ')' |
|
1724 * | il_call_operator prev_declared_fb_name '(' eol_list il_param_list ')' |
|
1725 */ |
|
1726 /* 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 */ |
|
1727 // SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list, symbol_c *called_fb_declaration) |
|
1728 void *constant_folding_c::visit(il_fb_call_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1729 |
|
1730 |
|
1731 /* TODO: handle function invocations... */ |
|
1732 /* | function_name '(' eol_list [il_param_list] ')' */ |
|
1733 /* NOTE: The parameter 'called_function_declaration' is used to pass data between the stage 3 and stage 4. */ |
|
1734 // SYM_REF2(il_formal_funct_call_c, function_name, il_param_list, symbol_c *called_function_declaration; int extensible_param_count;) |
|
1735 // void *constant_folding_c::visit(il_formal_funct_call_c *symbol) {return NULL;} |
|
1736 |
|
1737 |
|
1738 |
|
1739 /* Not needed, since we inherit from iterator_visitor_c */ |
|
1740 // void *constant_folding_c::visit(il_operand_list_c *symbol); |
|
1741 |
|
1742 |
|
1743 |
|
1744 /* | simple_instr_list il_simple_instruction */ |
|
1745 /* This object is referenced by il_expression_c objects */ |
|
1746 void *constant_folding_c::visit(simple_instr_list_c *symbol) { |
|
1747 if (symbol->n <= 0) |
|
1748 return NULL; /* List is empty! Nothing to do. */ |
|
1749 |
|
1750 for(int i = 0; i < symbol->n; i++) |
|
1751 symbol->elements[i]->accept(*this); |
|
1752 |
|
1753 /* This object has (inherits) the same cvalues as the il_jump_operator */ |
|
1754 symbol->const_value = symbol->elements[symbol->n-1]->const_value; |
|
1755 return NULL; |
|
1756 } |
|
1757 |
|
1758 |
|
1759 |
|
1760 // SYM_REF1(il_simple_instruction_c, il_simple_instruction, symbol_c *prev_il_instruction;) |
|
1761 void *constant_folding_c::visit(il_simple_instruction_c *symbol) { |
|
1762 if (symbol->prev_il_instruction.size() > 1) ERROR; /* There should be no labeled insructions inside an IL expression! */ |
|
1763 if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL; |
|
1764 else prev_il_instruction = symbol->prev_il_instruction[0]; |
|
1765 symbol->il_simple_instruction->accept(*this); |
|
1766 prev_il_instruction = NULL; |
|
1767 |
|
1768 /* This object has (inherits) the same cvalues as the il_jump_operator */ |
|
1769 symbol->const_value = symbol->il_simple_instruction->const_value; |
|
1770 return NULL; |
|
1771 } |
|
1772 |
|
1773 |
|
1774 /* |
|
1775 void *visit(il_param_list_c *symbol); |
|
1776 void *visit(il_param_assignment_c *symbol); |
|
1777 void *visit(il_param_out_assignment_c *symbol); |
|
1778 */ |
|
1779 |
|
1780 |
|
1781 /*******************/ |
|
1782 /* B 2.2 Operators */ |
|
1783 /*******************/ |
|
1784 void *constant_folding_c::visit( LD_operator_c *symbol) {return handle_move(symbol, il_operand);} |
|
1785 void *constant_folding_c::visit( LDN_operator_c *symbol) {return handle_not (symbol, il_operand);} |
|
1786 |
|
1787 /* NOTE: we are implementing a constant folding algorithm, not a constant propagation algorithm. |
|
1788 * For the constant propagation algorithm, the correct implementation of ST(N)_operator_c would be... |
|
1789 */ |
|
1790 //void *constant_folding_c::visit( ST_operator_c *symbol) {return handle_move(il_operand, symbol);} |
|
1791 //void *constant_folding_c::visit( STN_operator_c *symbol) {return handle_not (il_operand, symbol);} |
|
1792 void *constant_folding_c::visit( ST_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1793 void *constant_folding_c::visit( STN_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1794 |
|
1795 /* NOTE: the standard allows syntax in which the NOT operator is followed by an optional <il_operand> |
|
1796 * NOT [<il_operand>] |
|
1797 * However, it does not define the semantic of the NOT operation when the <il_operand> is specified. |
|
1798 * We therefore consider it an error if an il_operand is specified! This error will be caught elsewhere! |
|
1799 */ |
|
1800 void *constant_folding_c::visit( NOT_operator_c *symbol) {return handle_not(symbol, prev_il_instruction);} |
|
1801 |
|
1802 /* NOTE: Since we are only implementing a constant folding algorithm, and not a constant propagation algorithm, |
|
1803 * the following IL instructions do not change/set the value of the il_operand! |
|
1804 */ |
|
1805 void *constant_folding_c::visit( S_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1806 void *constant_folding_c::visit( R_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1807 |
|
1808 /* FB calls leave the value in the accumulator unchanged */ |
|
1809 void *constant_folding_c::visit( S1_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1810 void *constant_folding_c::visit( R1_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1811 void *constant_folding_c::visit( CLK_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1812 void *constant_folding_c::visit( CU_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1813 void *constant_folding_c::visit( CD_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1814 void *constant_folding_c::visit( PV_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1815 void *constant_folding_c::visit( IN_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1816 void *constant_folding_c::visit( PT_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1817 |
|
1818 void *constant_folding_c::visit( AND_operator_c *symbol) {return handle_and (symbol, prev_il_instruction, il_operand);} |
|
1819 void *constant_folding_c::visit( OR_operator_c *symbol) {return handle_or (symbol, prev_il_instruction, il_operand);} |
|
1820 void *constant_folding_c::visit( XOR_operator_c *symbol) {return handle_xor (symbol, prev_il_instruction, il_operand);} |
|
1821 void *constant_folding_c::visit( ANDN_operator_c *symbol) { handle_and (symbol, prev_il_instruction, il_operand); return handle_not(symbol, symbol);} |
|
1822 void *constant_folding_c::visit( ORN_operator_c *symbol) { handle_or (symbol, prev_il_instruction, il_operand); return handle_not(symbol, symbol);} |
|
1823 void *constant_folding_c::visit( XORN_operator_c *symbol) { handle_xor (symbol, prev_il_instruction, il_operand); return handle_not(symbol, symbol);} |
|
1824 |
|
1825 void *constant_folding_c::visit( ADD_operator_c *symbol) {return handle_add (symbol, prev_il_instruction, il_operand);} |
|
1826 void *constant_folding_c::visit( SUB_operator_c *symbol) {return handle_sub (symbol, prev_il_instruction, il_operand);} |
|
1827 void *constant_folding_c::visit( MUL_operator_c *symbol) {return handle_mul (symbol, prev_il_instruction, il_operand);} |
|
1828 void *constant_folding_c::visit( DIV_operator_c *symbol) {return handle_div (symbol, prev_il_instruction, il_operand);} |
|
1829 void *constant_folding_c::visit( MOD_operator_c *symbol) {return handle_mod (symbol, prev_il_instruction, il_operand);} |
|
1830 |
|
1831 void *constant_folding_c::visit( GT_operator_c *symbol) { handle_cmp (symbol, prev_il_instruction, il_operand, > );} |
|
1832 void *constant_folding_c::visit( GE_operator_c *symbol) { handle_cmp (symbol, prev_il_instruction, il_operand, >=);} |
|
1833 void *constant_folding_c::visit( EQ_operator_c *symbol) { handle_cmp (symbol, prev_il_instruction, il_operand, ==);} |
|
1834 void *constant_folding_c::visit( LT_operator_c *symbol) { handle_cmp (symbol, prev_il_instruction, il_operand, < );} |
|
1835 void *constant_folding_c::visit( LE_operator_c *symbol) { handle_cmp (symbol, prev_il_instruction, il_operand, <=);} |
|
1836 void *constant_folding_c::visit( NE_operator_c *symbol) { handle_cmp (symbol, prev_il_instruction, il_operand, !=);} |
|
1837 |
|
1838 void *constant_folding_c::visit( CAL_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1839 void *constant_folding_c::visit( RET_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1840 void *constant_folding_c::visit( JMP_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1841 void *constant_folding_c::visit( CALC_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1842 void *constant_folding_c::visit(CALCN_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1843 void *constant_folding_c::visit( RETC_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1844 void *constant_folding_c::visit(RETCN_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1845 void *constant_folding_c::visit( JMPC_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1846 void *constant_folding_c::visit(JMPCN_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);} |
|
1847 |
|
1848 |
|
1849 |
|
1850 |
1893 |
1851 /***************************************/ |
1894 /***************************************/ |
1852 /* B.3 - Language ST (Structured Text) */ |
1895 /* B.3 - Language ST (Structured Text) */ |
1853 /***************************************/ |
1896 /***************************************/ |
1854 /***********************/ |
1897 /***********************/ |
1855 /* B 3.1 - Expressions */ |
1898 /* B 3.1 - Expressions */ |
1856 /***********************/ |
1899 /***********************/ |
1857 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);} |
1900 #if DO_CONSTANT_PROPAGATION__ |
1858 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);} |
|
1859 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);} |
|
1860 |
|
1861 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, ==);} |
|
1862 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, !=);} |
|
1863 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, < );} |
|
1864 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, > );} |
|
1865 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, <=);} |
|
1866 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, >=);} |
|
1867 |
|
1868 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);} |
|
1869 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);} |
|
1870 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);} |
|
1871 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);} |
|
1872 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);} |
|
1873 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);} |
|
1874 |
|
1875 void *constant_folding_c::visit( neg_expression_c *symbol) {symbol-> exp->accept(*this); return handle_neg(symbol, symbol->exp);} |
|
1876 void *constant_folding_c::visit( not_expression_c *symbol) {symbol-> exp->accept(*this); return handle_not(symbol, symbol->exp);} |
|
1877 |
|
1878 /* TODO: handle function invocations... */ |
1901 /* TODO: handle function invocations... */ |
1879 // void *fill_candidate_datatypes_c::visit(function_invocation_c *symbol) {} |
1902 // void *fill_candidate_datatypes_c::visit(function_invocation_c *symbol) {} |
1880 |
1903 |
1881 |
1904 |
1882 |
|
1883 #if DO_CONSTANT_PROPAGATION__ |
|
1884 /*********************************/ |
1905 /*********************************/ |
1885 /* B 3.2.1 Assignment Statements */ |
1906 /* B 3.2.1 Assignment Statements */ |
1886 /*********************************/ |
1907 /*********************************/ |
1887 void *constant_folding_c::visit(assignment_statement_c *symbol) { |
1908 void *constant_propagation_c::visit(assignment_statement_c *symbol) { |
1888 std::string varName; |
1909 std::string varName; |
1889 |
1910 |
1890 symbol->r_exp->accept(*this); |
1911 symbol->r_exp->accept(*this); |
1891 symbol->l_exp->accept(*this); // if the lvalue has an array, do contant folding of the array indexes! |
1912 symbol->l_exp->accept(*this); // if the lvalue has an array, do contant folding of the array indexes! |
1892 symbol->l_exp->const_value = symbol->r_exp->const_value; |
1913 symbol->l_exp->const_value = symbol->r_exp->const_value; |