990 /*********************/ |
990 /*********************/ |
991 /* B 1.4 - Variables */ |
991 /* B 1.4 - Variables */ |
992 /*********************/ |
992 /*********************/ |
993 #if DO_CONSTANT_PROPAGATION__ |
993 #if DO_CONSTANT_PROPAGATION__ |
994 void *constant_folding_c::visit(symbolic_variable_c *symbol) { |
994 void *constant_folding_c::visit(symbolic_variable_c *symbol) { |
995 std::string varName; |
995 std::string varName = get_var_name_c::get_name(symbol->var_name)->value; |
996 |
996 if (values.count(varName) > 0) |
997 varName = get_var_name_c::get_name(symbol->var_name)->value; |
|
998 if (values.count(varName) > 0) { |
|
999 symbol->const_value = values[varName]; |
997 symbol->const_value = values[varName]; |
1000 } |
|
1001 return NULL; |
998 return NULL; |
1002 } |
999 } |
1003 #endif // DO_CONSTANT_PROPAGATION__ |
1000 #endif // DO_CONSTANT_PROPAGATION__ |
|
1001 |
|
1002 void *constant_folding_c::visit(symbolic_constant_c *symbol) { |
|
1003 std::string varName = get_var_name_c::get_name(symbol->var_name)->value; |
|
1004 if (values.count(varName) > 0) |
|
1005 symbol->const_value = values[varName]; |
|
1006 return NULL; |
|
1007 } |
|
1008 |
|
1009 |
|
1010 /******************************************/ |
|
1011 /* B 1.4.3 - Declaration & Initialisation */ |
|
1012 /******************************************/ |
|
1013 |
|
1014 /* Do the constant folding for VAR_EXTERNAL and VAR_GLOBAL pairs. |
|
1015 * This function is called from the declaration_check_c, since it has easy access to the extern<->global pairing information |
|
1016 * needed for this function to work. |
|
1017 */ |
|
1018 int constant_folding_c::handle_var_extern_global_pair(symbol_c *extern_var_name, symbol_c *extern_var_decl, symbol_c *global_var_name, symbol_c *global_var_decl) { |
|
1019 // the minimum infor we must get to make sense |
|
1020 if (NULL == global_var_decl) ERROR; |
|
1021 if (NULL == extern_var_name) ERROR; |
|
1022 |
|
1023 symbol_c *init_value = type_initial_value_c::get(global_var_decl); |
|
1024 if (NULL == init_value) return 0; // this is probably a FB datatype, for which no initial value exists! Do nothing and return. |
|
1025 |
|
1026 // Do constant folding of the initial value! |
|
1027 // This is required since this function may be called before we do the iterative constant folding of the complete library! |
|
1028 init_value->accept(*this); |
|
1029 |
|
1030 if (NULL != extern_var_name) extern_var_name->const_value = init_value->const_value; |
|
1031 if (NULL != extern_var_decl) extern_var_decl->const_value = init_value->const_value; // Note that each external variable declaration has its own datatype specification, so we can set this symbol's const_value too! |
|
1032 // we could leave the constant folding of the global variable itself for later, when we iteratively visit the whole library, but there is nor harm in doing it now! |
|
1033 if (NULL != global_var_name) global_var_name->const_value = init_value->const_value; |
|
1034 if (NULL != global_var_decl) global_var_decl->const_value = init_value->const_value; // Note that each external variable declaration has its own datatype specification, so we can set this symbol's const_value too! |
|
1035 return 0; |
|
1036 } |
|
1037 |
|
1038 |
|
1039 void *constant_folding_c::handle_var_list_decl(symbol_c *var_list, symbol_c *type_decl) { |
|
1040 symbol_c *init_value = type_initial_value_c::get(type_decl); |
|
1041 if (NULL == init_value) return NULL; // this is probably a FB datatype, for which no initial value exists! Do nothing and return. |
|
1042 init_value->accept(*this); // Do constant folding of the initial value! (we will probably be doing this multiple times for the same init value, but this is safe as the cvalue is idem-potent) |
|
1043 |
|
1044 list_c *list = dynamic_cast<list_c *>(var_list); |
|
1045 if (NULL == list) ERROR; |
|
1046 for (int i = 0; i < list->n; i++) { |
|
1047 token_c *var_name = dynamic_cast<token_c *>(list->elements[i]); |
|
1048 if (NULL == var_name) { |
|
1049 if (NULL != dynamic_cast<extensible_input_parameter_c *>(list->elements[i])) |
|
1050 continue; // this is an extensible standard function. Ignore this variable, and continue! |
|
1051 debug_c::print(list->elements[i]); |
|
1052 ERROR; |
|
1053 } |
|
1054 std::string varName = var_name->value; |
|
1055 values[varName] = init_value->const_value; |
|
1056 list->elements[i]->const_value = init_value->const_value; |
|
1057 } |
|
1058 return NULL; |
|
1059 } |
|
1060 |
|
1061 /* | var1_list ',' variable_name */ |
|
1062 //SYM_LIST(var1_list_c) // Not needed! |
|
1063 //SYM_REF0(constant_option_c) // Not needed! |
|
1064 //SYM_REF0(retain_option_c) // Not needed! |
|
1065 //SYM_REF0(non_retain_option_c) // Not needed! |
|
1066 |
|
1067 |
|
1068 /* spec_init is one of the following... |
|
1069 * simple_spec_init_c * |
|
1070 * subrange_spec_init_c * |
|
1071 * enumerated_spec_init_c * |
|
1072 */ |
|
1073 // SYM_REF2(var1_init_decl_c, var1_list, spec_init) |
|
1074 void *constant_folding_c::visit(var1_init_decl_c *symbol) {return handle_var_list_decl(symbol->var1_list, symbol->spec_init);} |
|
1075 |
|
1076 /* | [var1_list ','] variable_name integer '..' */ |
|
1077 /* NOTE: This is an extension to the standard!!! */ |
|
1078 //SYM_REF2(extensible_input_parameter_c, var_name, first_index) // Not needed! |
|
1079 /* var1_list ':' array_spec_init */ |
|
1080 //SYM_REF2(array_var_init_decl_c, var1_list, array_spec_init) // We do not yet handle arrays! |
|
1081 /* var1_list ':' initialized_structure */ |
|
1082 //SYM_REF2(structured_var_init_decl_c, var1_list, initialized_structure) // We do not yet handle structures! |
|
1083 /* fb_name_list ':' function_block_type_name ASSIGN structure_initialization */ |
|
1084 //SYM_REF2(fb_name_decl_c, fb_name_list, fb_spec_init) // We do not yet handle FBs! |
|
1085 /* fb_name_list ',' fb_name */ |
|
1086 //SYM_LIST(fb_name_list_c) // Not needed! |
|
1087 /* VAR_INPUT [option] input_declaration_list END_VAR */ |
|
1088 /* option -> the RETAIN/NON_RETAIN/<NULL> directive... */ |
|
1089 //SYM_REF3(input_declarations_c, option, input_declaration_list, method) |
|
1090 void *constant_folding_c::visit(input_declarations_c *symbol) {return NULL;} // Input variables can take any initial value, so we can not set the const_value annotation! |
|
1091 |
|
1092 /* helper symbol for input_declarations */ |
|
1093 //SYM_LIST(input_declaration_list_c) // Not needed! |
|
1094 /* VAR_OUTPUT [RETAIN | NON_RETAIN] var_init_decl_list END_VAR */ |
|
1095 /* option -> may be NULL ! */ |
|
1096 //SYM_REF3(output_declarations_c, option, var_init_decl_list, method) // Not needed since we inherit from iterator_visitor_c! |
|
1097 |
|
1098 /* VAR_IN_OUT var_declaration_list END_VAR */ |
|
1099 //SYM_REF1(input_output_declarations_c, var_declaration_list) |
|
1100 void *constant_folding_c::visit(input_output_declarations_c *symbol) {return NULL;} // Input variables can take any initial value, so we can not set the const_value annotation! |
|
1101 /* helper symbol for input_output_declarations */ |
|
1102 /* var_declaration_list var_declaration ';' */ |
|
1103 //SYM_LIST(var_declaration_list_c) // Not needed since we inherit from iterator_visitor_c! |
|
1104 /* var1_list ':' array_specification */ |
|
1105 //SYM_REF2(array_var_declaration_c, var1_list, array_specification) // We do not yet handle arrays! |
|
1106 /* var1_list ':' structure_type_name */ |
|
1107 //SYM_REF2(structured_var_declaration_c, var1_list, structure_type_name) // We do not yet handle structures! |
|
1108 /* VAR [CONSTANT] var_init_decl_list END_VAR */ |
|
1109 /* option -> may be NULL ! */ |
|
1110 //SYM_REF2(var_declarations_c, option, var_init_decl_list) // Not needed: we inherit from iterator_c |
|
1111 |
|
1112 /* VAR RETAIN var_init_decl_list END_VAR */ |
|
1113 //SYM_REF1(retentive_var_declarations_c, var_init_decl_list) |
|
1114 void *constant_folding_c::visit(retentive_var_declarations_c *symbol) {return NULL;} // Retentive variables can take any initial value, so we can not set the const_value annotation! |
|
1115 /* VAR [CONSTANT|RETAIN|NON_RETAIN] located_var_decl_list END_VAR */ |
|
1116 /* option -> may be NULL ! */ |
|
1117 |
|
1118 #if 0 |
|
1119 // TODO |
|
1120 SYM_REF2(located_var_declarations_c, option, located_var_decl_list) |
|
1121 /* helper symbol for located_var_declarations */ |
|
1122 /* located_var_decl_list located_var_decl ';' */ |
|
1123 SYM_LIST(located_var_decl_list_c) |
|
1124 /* [variable_name] location ':' located_var_spec_init */ |
|
1125 /* variable_name -> may be NULL ! */ |
|
1126 SYM_REF3(located_var_decl_c, variable_name, location, located_var_spec_init) |
|
1127 #endif |
|
1128 |
|
1129 /*| VAR_EXTERNAL [CONSTANT] external_declaration_list END_VAR */ |
|
1130 /* option -> may be NULL ! */ |
|
1131 // SYM_REF2(external_var_declarations_c, option, external_declaration_list) |
|
1132 // void *constant_folding_c::visit(external_var_declarations_c *symbol) {} // Not needed: we inherit from iterator_c |
|
1133 |
|
1134 /* helper symbol for external_var_declarations */ |
|
1135 /*| external_declaration_list external_declaration';' */ |
|
1136 // SYM_LIST(external_declaration_list_c) |
|
1137 // void *constant_folding_c::visit(external_declaration_list_c *symbol) {} // Not needed: we inherit from iterator_c |
|
1138 |
|
1139 /* global_var_name ':' (simple_specification|subrange_specification|enumerated_specification|array_specification|prev_declared_structure_type_name|function_block_type_name */ |
|
1140 //SYM_REF2(external_declaration_c, global_var_name, specification) |
|
1141 void *constant_folding_c::visit(external_declaration_c *symbol) { |
|
1142 // Note that specification->const_value will have been set by handle_var_extern_global_pair, which is called from declaration_check_c |
|
1143 symbol->global_var_name->const_value = symbol->specification->const_value; |
|
1144 std::string varName = get_var_name_c::get_name(symbol->global_var_name)->value; |
|
1145 values[varName] = symbol->specification->const_value; |
|
1146 return NULL; |
|
1147 } |
|
1148 |
|
1149 /* Visitors related to GLOBAL variables are not really needed, |
|
1150 * as they are already handled by handle_var_extern_global_pair, which is called from declaration_check_c |
|
1151 * |
|
1152 * This is done like this because we need to know the pairing of external<->global variables to get the cvalue |
|
1153 * from the global variable. Since the external<->global pairing information is available in the declaration_check_c, |
|
1154 * we have that class call the constant_folding_c::handle_var_extern_global_pair(), which will actually do the |
|
1155 * constant folding of the global and the external variable declarations! |
|
1156 */ |
|
1157 /*| VAR_GLOBAL [CONSTANT|RETAIN] global_var_decl_list END_VAR */ |
|
1158 /* option -> may be NULL ! */ |
|
1159 // SYM_REF2(global_var_declarations_c, option, global_var_decl_list) |
|
1160 /* helper symbol for global_var_declarations */ |
|
1161 /*| global_var_decl_list global_var_decl ';' */ |
|
1162 // SYM_LIST(global_var_decl_list_c) |
|
1163 /*| global_var_spec ':' [located_var_spec_init|function_block_type_name] */ |
|
1164 /* type_specification ->may be NULL ! */ |
|
1165 //SYM_REF2(global_var_decl_c, global_var_spec, type_specification) |
|
1166 /*| global_var_name location */ |
|
1167 //SYM_REF2(global_var_spec_c, global_var_name, location) |
|
1168 /* AT direct_variable */ |
|
1169 //SYM_REF1(location_c, direct_variable) |
|
1170 /*| global_var_list ',' global_var_name */ |
|
1171 //SYM_LIST(global_var_list_c) |
|
1172 |
|
1173 |
|
1174 #if 0 |
|
1175 // TODO |
|
1176 /* var1_list ':' single_byte_string_spec */ |
|
1177 SYM_REF2(single_byte_string_var_declaration_c, var1_list, single_byte_string_spec) |
|
1178 /* STRING ['[' integer ']'] [ASSIGN single_byte_character_string] */ |
|
1179 /* integer ->may be NULL ! */ |
|
1180 /* single_byte_character_string ->may be NULL ! */ |
|
1181 SYM_REF2(single_byte_string_spec_c, string_spec, single_byte_character_string) |
|
1182 /* STRING ['[' integer ']'] */ |
|
1183 /* integer ->may be NULL ! */ |
|
1184 SYM_REF2(single_byte_limited_len_string_spec_c, string_type_name, character_string_len) |
|
1185 /* WSTRING ['[' integer ']'] */ |
|
1186 /* integer ->may be NULL ! */ |
|
1187 SYM_REF2(double_byte_limited_len_string_spec_c, string_type_name, character_string_len) |
|
1188 /* var1_list ':' double_byte_string_spec */ |
|
1189 SYM_REF2(double_byte_string_var_declaration_c, var1_list, double_byte_string_spec) |
|
1190 /* WSTRING ['[' integer ']'] [ASSIGN double_byte_character_string] */ |
|
1191 /* integer ->may be NULL ! */ |
|
1192 /* double_byte_character_string ->may be NULL ! */ |
|
1193 SYM_REF2(double_byte_string_spec_c, string_spec, double_byte_character_string) |
|
1194 /*| VAR [RETAIN|NON_RETAIN] incompl_located_var_decl_list END_VAR */ |
|
1195 /* option ->may be NULL ! */ |
|
1196 SYM_REF2(incompl_located_var_declarations_c, option, incompl_located_var_decl_list) |
|
1197 /* helper symbol for incompl_located_var_declarations */ |
|
1198 /*| incompl_located_var_decl_list incompl_located_var_decl ';' */ |
|
1199 SYM_LIST(incompl_located_var_decl_list_c) |
|
1200 /* variable_name incompl_location ':' var_spec */ |
|
1201 SYM_REF3(incompl_located_var_decl_c, variable_name, incompl_location, var_spec) |
|
1202 /* AT incompl_location_token */ |
|
1203 SYM_TOKEN(incompl_location_c) |
|
1204 /* intermediate helper symbol for: |
|
1205 * - non_retentive_var_decls |
|
1206 * - output_declarations |
|
1207 */ |
|
1208 SYM_LIST(var_init_decl_list_c) |
|
1209 #endif |
|
1210 |
|
1211 |
|
1212 /***********************/ |
|
1213 /* B 1.5.1 - Functions */ |
|
1214 /***********************/ |
|
1215 /* enumvalue_symtable is filled in by enum_declaration_check_c, during stage3 semantic verification, with a list of all enumerated constants declared inside this POU */ |
|
1216 //SYM_REF4(function_declaration_c, derived_function_name, type_name, var_declarations_list, function_body, enumvalue_symtable_t enumvalue_symtable;) |
|
1217 void *constant_folding_c::visit(function_declaration_c *symbol) { |
|
1218 values.clear(); /* Clear global map */ |
|
1219 /* Add initial value of all declared variables into Values map. */ |
|
1220 symbol->var_declarations_list->accept(*this); |
|
1221 symbol->function_body->accept(*this); |
|
1222 return NULL; |
|
1223 } |
|
1224 |
|
1225 |
|
1226 /*****************************/ |
|
1227 /* B 1.5.2 - Function Blocks */ |
|
1228 /*****************************/ |
|
1229 /* FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */ |
|
1230 /* enumvalue_symtable is filled in by enum_declaration_check_c, during stage3 semantic verification, with a list of all enumerated constants declared inside this POU */ |
|
1231 //SYM_REF3(function_block_declaration_c, fblock_name, var_declarations, fblock_body, enumvalue_symtable_t enumvalue_symtable;) |
|
1232 void *constant_folding_c::visit(function_block_declaration_c *symbol) { |
|
1233 values.clear(); /* Clear global map */ |
|
1234 /* Add initial value of all declared variables into Values map. */ |
|
1235 symbol->var_declarations->accept(*this); |
|
1236 symbol->fblock_body->accept(*this); |
|
1237 return NULL; |
|
1238 } |
1004 |
1239 |
1005 |
1240 |
1006 /**********************/ |
1241 /**********************/ |
1007 /* B 1.5.3 - Programs */ |
1242 /* B 1.5.3 - Programs */ |
1008 /**********************/ |
1243 /**********************/ |
1009 #if DO_CONSTANT_PROPAGATION__ |
1244 /* PROGRAM program_type_name program_var_declarations_list function_block_body END_PROGRAM */ |
|
1245 //SYM_REF3(program_declaration_c, program_type_name, var_declarations, function_block_body, enumvalue_symtable_t enumvalue_symtable;) |
1010 void *constant_folding_c::visit(program_declaration_c *symbol) { |
1246 void *constant_folding_c::visit(program_declaration_c *symbol) { |
1011 symbol_c *var_name; |
1247 values.clear(); /* Clear global map */ |
1012 |
1248 /* Add initial value of all declared variables into Values map. */ |
1013 symbol->var_declarations->accept(*this); |
1249 symbol->var_declarations->accept(*this); |
1014 values.clear(); /* Clear global map */ |
|
1015 search_var_instance_decl_c search_var_instance_decl(symbol); |
|
1016 function_param_iterator_c fpi(symbol); |
|
1017 while((var_name = fpi.next()) != NULL) { |
|
1018 std::string varName = get_var_name_c::get_name(var_name)->value; |
|
1019 symbol_c *varDecl = search_var_instance_decl.get_decl(var_name); |
|
1020 values[varName] = varDecl->const_value; |
|
1021 } |
|
1022 /* Add all variables declared into Values map and put them to initial value */ |
|
1023 symbol->function_block_body->accept(*this); |
1250 symbol->function_block_body->accept(*this); |
1024 return NULL; |
1251 return NULL; |
1025 } |
1252 } |
1026 #endif // DO_CONSTANT_PROPAGATION__ |
|
1027 |
1253 |
1028 |
1254 |
1029 /****************************************/ |
1255 /****************************************/ |
1030 /* B.2 - Language IL (Instruction List) */ |
1256 /* B.2 - Language IL (Instruction List) */ |
1031 /****************************************/ |
1257 /****************************************/ |