stage3/constant_folding.cc
changeset 969 706a152731ab
parent 968 649e03abbfc1
child 970 0ede7ca157e2
equal deleted inserted replaced
968:649e03abbfc1 969:706a152731ab
   233 		} else {\
   233 		} else {\
   234 			resValue._##dtype.set(c1._##dtype.get());\
   234 			resValue._##dtype.set(c1._##dtype.get());\
   235 		}\
   235 		}\
   236 }
   236 }
   237 
   237 
   238 typedef std::map <std::string, const_value_c> map_values_t;
       
   239 
       
   240 static map_values_t values;
       
   241 
   238 
   242 
   239 
   243 
   240 
   244 /***********************************************************************/
   241 /***********************************************************************/
   245 /***********************************************************************/
   242 /***********************************************************************/
   724 		SET_CVALUE(real64, symbol, pow(GET_CVALUE(real64, oper1), GET_CVALUE(uint64, oper2)));
   721 		SET_CVALUE(real64, symbol, pow(GET_CVALUE(real64, oper1), GET_CVALUE(uint64, oper2)));
   725 	CHECK_OVERFLOW_real64(symbol);
   722 	CHECK_OVERFLOW_real64(symbol);
   726 	return NULL;
   723 	return NULL;
   727 }
   724 }
   728 
   725 
   729 static map_values_t inner_left_join_values(map_values_t m1, map_values_t m2) {
   726 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) {
   730 	map_values_t::const_iterator itr;
   727 	constant_folding_c::map_values_t::const_iterator itr;
   731 	map_values_t ret;
   728 	constant_folding_c::map_values_t ret;
   732 
   729 
   733 	itr = m1.begin();
   730 	itr = m1.begin();
   734 	for ( ; itr != m1.end(); ++itr) {
   731 	for ( ; itr != m1.end(); ++itr) {
   735 		std::string name = itr->first;
   732 		std::string name = itr->first;
   736 		const_value_c value;
   733 		const_value_c value;
  1169 // void *constant_folding_c::visit(external_declaration_list_c *symbol) {} // Not needed: we inherit from iterator_c
  1166 // void *constant_folding_c::visit(external_declaration_list_c *symbol) {} // Not needed: we inherit from iterator_c
  1170 
  1167 
  1171 /*  global_var_name ':' (simple_specification|subrange_specification|enumerated_specification|array_specification|prev_declared_structure_type_name|function_block_type_name */
  1168 /*  global_var_name ':' (simple_specification|subrange_specification|enumerated_specification|array_specification|prev_declared_structure_type_name|function_block_type_name */
  1172 //SYM_REF2(external_declaration_c, global_var_name, specification)
  1169 //SYM_REF2(external_declaration_c, global_var_name, specification)
  1173 void *constant_folding_c::visit(external_declaration_c *symbol) {
  1170 void *constant_folding_c::visit(external_declaration_c *symbol) {
  1174   // Note that specification->const_value will have been set by handle_var_extern_global_pair, which is called from declaration_check_c
  1171   // Note that specification->const_value will have been set by handle_var_extern_global_pair(), which is called from declaration_check_c
  1175   symbol->global_var_name->const_value = symbol->specification->const_value;
  1172   symbol->global_var_name->const_value = symbol->specification->const_value;
  1176   if (fixed_init_value_) {
  1173   if (fixed_init_value_) {
  1177     std::string varName = get_var_name_c::get_name(symbol->global_var_name)->value;
  1174     std::string varName = get_var_name_c::get_name(symbol->global_var_name)->value;
  1178     values[varName] = symbol->specification->const_value;
  1175     values[varName] = symbol->specification->const_value;
  1179   }
  1176   }
  1180   // If the datatype specification is a subrange or array, do constant folding of all the literals in that type declaration... (ex: literals in array subrange limits)
  1177   // If the datatype specification is a subrange or array, do constant folding of all the literals in that type declaration... (ex: literals in array subrange limits)
  1181   symbol->specification->accept(*this);  // should never get to change the const_value of the symbol->specification symbol (only its children!).
  1178   symbol->specification->accept(*this);  // should never get to change the const_value of the symbol->specification symbol (only its children!).
  1182   return NULL;
  1179   return NULL;
  1183 }
  1180 }
  1184 
  1181 
  1185 /* Visitors related to GLOBAL variables are not really needed, 
  1182 /* NOTE that the constant folding of GLOBAL variables is already handled by handle_var_extern_global_pair, which 
  1186  * as they are already handled by handle_var_extern_global_pair, which is called from declaration_check_c 
  1183  * is called from declaration_check_c,
  1187  * 
       
  1188  * This is done like this because we need to know the pairing of external<->global variables to get the cvalue
  1184  * This is done like this because we need to know the pairing of external<->global variables to get the cvalue
  1189  * from the global variable. Since the external<->global pairing information is available in the declaration_check_c,
  1185  * from the global variable. Since the external<->global pairing information is available in the declaration_check_c,
  1190  * we have that class call the constant_folding_c::handle_var_extern_global_pair(), which will actually do the 
  1186  * we have that class call the constant_folding_c::handle_var_extern_global_pair(), which will actually do the 
  1191  * constant folding of the global and the external variable declarations!
  1187  * constant folding of the global and the external variable declarations!
  1192  */
  1188  */
       
  1189 /* NOTE: The constant propagation portion of this algorithm must still be done here!!
       
  1190  * Even though the constant folding of GLOBAL variables are already handled by handle_var_extern_global_pair(),
       
  1191  * we must still visit them here, since when doing constant propagation of a Configuration or a Resource we need the
       
  1192  * values of constant variables to be placed in the values[] map, as these same variables may be used to declare
       
  1193  * arrays of a variable size
       
  1194  *    VAR_GLOBAL CONSTANT max     : INT := 42;             END_VAR
       
  1195  *    VAR_GLOBAL          array_v : ARRAY [1..max] of INT; END_VAR  <---- NOTE the use of 'max' in the subrange!
       
  1196  */
  1193 /*| VAR_GLOBAL [CONSTANT|RETAIN] global_var_decl_list END_VAR */
  1197 /*| VAR_GLOBAL [CONSTANT|RETAIN] global_var_decl_list END_VAR */
  1194 /* option -> may be NULL ! */
  1198 /* option -> may be NULL ! */
  1195 // SYM_REF2(global_var_declarations_c, option, global_var_decl_list)
  1199 // SYM_REF2(global_var_declarations_c, option, global_var_decl_list)
       
  1200 /* Note that calling handle_var_decl() will result in doing constant folding of literals (of datatype initial values)
       
  1201  * that were already constant folded by the method handle_var_extern_global_pair()
       
  1202  * Nevertheless, since constant folding is idem-potent, it is simpler to just call handle_var_decl() instead
       
  1203  * of writing some code specific for this situation!
       
  1204  */
       
  1205 void *constant_folding_c::visit(global_var_declarations_c *symbol) {return handle_var_decl(symbol->global_var_decl_list, is_constant(symbol->option));}
       
  1206 
       
  1207 
  1196 /* helper symbol for global_var_declarations */
  1208 /* helper symbol for global_var_declarations */
  1197 /*| global_var_decl_list global_var_decl ';' */
  1209 /*| global_var_decl_list global_var_decl ';' */
  1198 // SYM_LIST(global_var_decl_list_c)
  1210 // SYM_LIST(global_var_decl_list_c)
       
  1211 // void *constant_folding_c::visit(global_var_decl_list_c *symbol) {} // Not needed: we inherit from iterator_c
       
  1212 
  1199 /*| global_var_spec ':' [located_var_spec_init|function_block_type_name] */
  1213 /*| global_var_spec ':' [located_var_spec_init|function_block_type_name] */
  1200 /* type_specification ->may be NULL ! */
  1214 /* type_specification ->may be NULL ! */
  1201 //SYM_REF2(global_var_decl_c, global_var_spec, type_specification)
  1215 //SYM_REF2(global_var_decl_c, global_var_spec, type_specification)
       
  1216 void *constant_folding_c::visit(global_var_decl_c *symbol) {
       
  1217   /* global_var_spec may be either a global_var_spec_c or a global_var_list_c.
       
  1218    * Since we already have a nice method that handles var lists (handle_var_list_decl() )
       
  1219    * if it is a global_var_spec_c we will create a temporary list so we can call that method!
       
  1220    */
       
  1221   global_var_spec_c *var_spec = dynamic_cast<global_var_spec_c *>(symbol->global_var_spec);
       
  1222   if (NULL == var_spec) {
       
  1223     // global_var_spec is a global_var_list_c
       
  1224     return handle_var_list_decl(symbol->global_var_spec, symbol->type_specification);
       
  1225   } else {
       
  1226     global_var_list_c var_list;
       
  1227     var_list.add_element(var_spec->global_var_name);
       
  1228     return handle_var_list_decl(&var_list, symbol->type_specification);
       
  1229   }
       
  1230 }
       
  1231 
       
  1232 
  1202 /*| global_var_name location */
  1233 /*| global_var_name location */
  1203 //SYM_REF2(global_var_spec_c, global_var_name, location)
  1234 //SYM_REF2(global_var_spec_c, global_var_name, location)              // Not needed!
       
  1235 
  1204 /*  AT direct_variable */
  1236 /*  AT direct_variable */
  1205 //SYM_REF1(location_c, direct_variable)
  1237 //SYM_REF1(location_c, direct_variable)                               // Not needed!
       
  1238 
  1206 /*| global_var_list ',' global_var_name */
  1239 /*| global_var_list ',' global_var_name */
  1207 //SYM_LIST(global_var_list_c)
  1240 //SYM_LIST(global_var_list_c)                                         // Not needed!
  1208 
  1241 
  1209 
  1242 
  1210 #if 0  
  1243 #if 0  
  1211 // TODO
  1244 // TODO
       
  1245 // We do not do constant folding of strings yet, so there is no need to implement this now!
  1212 /*  var1_list ':' single_byte_string_spec */
  1246 /*  var1_list ':' single_byte_string_spec */
  1213 SYM_REF2(single_byte_string_var_declaration_c, var1_list, single_byte_string_spec)
  1247 SYM_REF2(single_byte_string_var_declaration_c, var1_list, single_byte_string_spec)
  1214 /*  STRING ['[' integer ']'] [ASSIGN single_byte_character_string] */
  1248 /*  STRING ['[' integer ']'] [ASSIGN single_byte_character_string] */
  1215 /* integer ->may be NULL ! */
  1249 /* integer ->may be NULL ! */
  1216 /* single_byte_character_string ->may be NULL ! */
  1250 /* single_byte_character_string ->may be NULL ! */
  1318 	symbol->function_block_body->accept(*this);
  1352 	symbol->function_block_body->accept(*this);
  1319 	return NULL;
  1353 	return NULL;
  1320 }
  1354 }
  1321 
  1355 
  1322 
  1356 
       
  1357 /********************************/
       
  1358 /* B 1.7 Configuration elements */
       
  1359 /********************************/
       
  1360 
       
  1361 /*
       
  1362 CONFIGURATION configuration_name
       
  1363    optional_global_var_declarations
       
  1364    (resource_declaration_list | single_resource_declaration)
       
  1365    optional_access_declarations
       
  1366    optional_instance_specific_initializations
       
  1367 END_CONFIGURATION
       
  1368 */
       
  1369 /* 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 */
       
  1370 // SYM_REF5(configuration_declaration_c, configuration_name, global_var_declarations, resource_declarations, access_declarations, instance_specific_initializations, 
       
  1371 //          enumvalue_symtable_t enumvalue_symtable; localvar_symbmap_t localvar_symbmap; localvar_symbvec_t localvar_symbvec;)
       
  1372 void *constant_folding_c::visit(configuration_declaration_c *symbol) {
       
  1373 	values.clear(); /* Clear global map */
       
  1374 	/* Add initial value of all declared variables into Values map. */
       
  1375 	function_pou_ = false;
       
  1376 	return iterator_visitor_c::visit(symbol); // let the base iterator class handle the rest (basically iterate through the whole configuration and do the constant folding!
       
  1377 }
       
  1378 
       
  1379 
       
  1380 /* helper symbol for configuration_declaration */
       
  1381 // SYM_LIST(resource_declaration_list_c)           // Not needed: we inherit from iterator_c
       
  1382 
       
  1383 /*
       
  1384 RESOURCE resource_name ON resource_type_name
       
  1385    optional_global_var_declarations
       
  1386    single_resource_declaration
       
  1387 END_RESOURCE
       
  1388 */
       
  1389 /* 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 */
       
  1390 // SYM_REF4(resource_declaration_c, resource_name, resource_type_name, global_var_declarations, resource_declaration, 
       
  1391 //          enumvalue_symtable_t enumvalue_symtable; localvar_symbmap_t localvar_symbmap; localvar_symbvec_t localvar_symbvec;)
       
  1392 void *constant_folding_c::visit(resource_declaration_c *symbol) {
       
  1393 	values.clear(); /* Clear global map */
       
  1394 	/* Add initial value of all declared variables into Values map. */
       
  1395 	function_pou_ = false;
       
  1396 	return iterator_visitor_c::visit(symbol); // let the base iterator class handle the rest (basically iterate through the whole configuration and do the constant folding!
       
  1397 }
       
  1398 
       
  1399 
       
  1400 
       
  1401 /* task_configuration_list program_configuration_list */
       
  1402 // SYM_REF2(single_resource_declaration_c, task_configuration_list, program_configuration_list)
       
  1403 /* helper symbol for single_resource_declaration */
       
  1404 // SYM_LIST(task_configuration_list_c)
       
  1405 /* helper symbol for single_resource_declaration */
       
  1406 // SYM_LIST(program_configuration_list_c)
       
  1407 /* helper symbol for: (access_path, instance_specific_init) */
       
  1408 // SYM_LIST(any_fb_name_list_c)
       
  1409 /*  [resource_name '.'] global_var_name ['.' structure_element_name] */
       
  1410 // SYM_REF3(global_var_reference_c, resource_name, global_var_name, structure_element_name)
       
  1411 /*  prev_declared_program_name '.' symbolic_variable */
       
  1412 // SYM_REF2(program_output_reference_c, program_name, symbolic_variable)
       
  1413 /*  TASK task_name task_initialization */
       
  1414 // SYM_REF2(task_configuration_c, task_name, task_initialization)
       
  1415 /*  '(' [SINGLE ASSIGN data_source ','] [INTERVAL ASSIGN data_source ','] PRIORITY ASSIGN integer ')' */
       
  1416 // SYM_REF3(task_initialization_c, single_data_source, interval_data_source, priority_data_source)
       
  1417 /*  PROGRAM [RETAIN | NON_RETAIN] program_name [WITH task_name] ':' program_type_name ['(' prog_conf_elements ')'] */
       
  1418 /* NOTE: The parameter 'called_prog_declaration'is used to pass data between stage 3 and stage4 */
       
  1419 // SYM_REF5(program_configuration_c, retain_option, program_name, task_name, program_type_name, prog_conf_elements,
       
  1420 //          symbol_c *called_prog_declaration;)
       
  1421 /* prog_conf_elements ',' prog_conf_element */
       
  1422 // SYM_LIST(prog_conf_elements_c)
       
  1423 /*  fb_name WITH task_name */
       
  1424 // SYM_REF2(fb_task_c, fb_name, task_name)
       
  1425 /*  any_symbolic_variable ASSIGN prog_data_source */
       
  1426 // SYM_REF2(prog_cnxn_assign_c, symbolic_variable, prog_data_source)
       
  1427 /* any_symbolic_variable SENDTO data_sink */
       
  1428 // SYM_REF2(prog_cnxn_sendto_c, symbolic_variable, data_sink)
       
  1429 /* VAR_CONFIG instance_specific_init_list END_VAR */
       
  1430 // SYM_REF1(instance_specific_initializations_c, instance_specific_init_list)
       
  1431 /* helper symbol for instance_specific_initializations */
       
  1432 // SYM_LIST(instance_specific_init_list_c)
       
  1433 /* resource_name '.' program_name '.' {fb_name '.'}
       
  1434     ((variable_name [location] ':' located_var_spec_init) | (fb_name ':' fb_initialization))
       
  1435 */
       
  1436 // SYM_REF6(instance_specific_init_c, resource_name, program_name, any_fb_name_list, variable_name, location, initialization)
       
  1437 /* helper symbol for instance_specific_init */
       
  1438 /* function_block_type_name ':=' structure_initialization */
       
  1439 // SYM_REF2(fb_initialization_c, function_block_type_name, structure_initialization)
       
  1440 
       
  1441 
       
  1442 
       
  1443 
  1323 /****************************************/
  1444 /****************************************/
  1324 /* B.2 - Language IL (Instruction List) */
  1445 /* B.2 - Language IL (Instruction List) */
  1325 /****************************************/
  1446 /****************************************/
  1326 /***********************************/
  1447 /***********************************/
  1327 /* B 2.1 Instructions and Operands */
  1448 /* B 2.1 Instructions and Operands */