1350 * times (if it is instantiated multiple times in the same configuration, or once |
1350 * times (if it is instantiated multiple times in the same configuration, or once |
1351 * in several configurations). This should not be a problem because the constant |
1351 * in several configurations). This should not be a problem because the constant |
1352 * propagation algorithm is idem-potent (assuming the same constant values in the |
1352 * propagation algorithm is idem-potent (assuming the same constant values in the |
1353 * beginning), and we can use these multiple calls to the same POU to detect if |
1353 * beginning), and we can use these multiple calls to the same POU to detect if |
1354 * the situation mentioned in (1) is ocurring. |
1354 * the situation mentioned in (1) is ocurring. |
|
1355 * Note too that FBs may also include VAR_EXTERN CONSTANT variables, which must also |
|
1356 * get their constant value from the corresponding global variable (declared in the |
|
1357 * configuration, program and FBs currently in scope). For this reason, when a FB |
|
1358 * variable is instantiated inside a configuration, program or FB, we must recursively |
|
1359 * visit the FB type declaration! |
1355 * - After analysing all the configurations, we analyse all the other POUs that have |
1360 * - After analysing all the configurations, we analyse all the other POUs that have |
1356 * not yet been called (because they are not instantiated directly from within |
1361 * not yet been called (because they are not instantiated directly from within |
1357 * any configuration - e.g. functions, and most FBs!). |
1362 * any configuration - e.g. functions, and most FBs!). |
1358 * It is for this reason (3) why we have the two loops on the following code! |
1363 * It is for this reason (3) why we have the two loops on the following code! |
1359 */ |
1364 */ |
1412 } |
1417 } |
1413 |
1418 |
1414 void *constant_propagation_c::handle_var_list_decl(symbol_c *var_list, symbol_c *type_decl, bool is_global_var) { |
1419 void *constant_propagation_c::handle_var_list_decl(symbol_c *var_list, symbol_c *type_decl, bool is_global_var) { |
1415 type_decl->accept(*this); // Do constant folding of the initial value, and literals in subranges! (we will probably be doing this multiple times for the same init value, but this is safe as the cvalue is idem-potent) |
1420 type_decl->accept(*this); // Do constant folding of the initial value, and literals in subranges! (we will probably be doing this multiple times for the same init value, but this is safe as the cvalue is idem-potent) |
1416 symbol_c *init_value = type_initial_value_c::get(type_decl); |
1421 symbol_c *init_value = type_initial_value_c::get(type_decl); |
1417 if (NULL == init_value) {return NULL;} // this is probably a FB datatype, for which no initial value exists! Do nothing and return. |
1422 |
|
1423 /* There are two main possibilities here: either we are instantiating FBs, or some other variable. |
|
1424 * (1) if it is a FB, we must recursively visit the FB type declaration, to let any VAR_EXTERN |
|
1425 * variables there get their initial value from the current var_global_values[] map!! |
|
1426 * (2) if it is a normal variable, we will store the initial value of that variable in the values[] map. |
|
1427 * (and also store it in the var_global_values[] map is it is a VAR_GLOBAL variable!) |
|
1428 */ |
|
1429 |
|
1430 /* Check whether we have situation (1) mentioned above! */ |
|
1431 /* find the possible declaration (i.e. the datatype) of the possible FB being instantiated */ |
|
1432 // NOTE: we do not use symbol->datatype so this const propagation algorithm will not depend on the fill/narrow datatypes algorithm! |
|
1433 function_block_type_symtable_t::iterator itr = function_block_type_symtable.end(); // assume not a FB! |
|
1434 symbol_c *type_symbol = spec_init_sperator_c::get_spec(type_decl); |
|
1435 token_c *type_name = dynamic_cast<token_c *>(type_symbol); |
|
1436 if (type_name != NULL) |
|
1437 itr = function_block_type_symtable.find(type_name); |
|
1438 if (itr != function_block_type_symtable.end()) { |
|
1439 // Handle the situation (1) mentioned above, i.e. handle the instantiation of FBs. |
|
1440 // ------------------------------------------------------------------------------- |
|
1441 // Remmeber that in this case we will recursively visit the FB type declaration!! |
|
1442 function_block_declaration_c *fb_type = itr->second; |
|
1443 if (NULL == fb_type) ERROR; // syntax parsing should not allow this! |
|
1444 // TODO: detect whether we are already currently visiting this exact same FB declaration (possible with -p option), so we do not get into an infinite loop!! |
|
1445 fb_type->accept(*this); |
|
1446 return NULL; |
|
1447 } |
|
1448 |
|
1449 // Handle the situation (2) mentioned above, i.e. handle the instantiation of non-FB variables. |
|
1450 // -------------------------------------------------------------------------------------------- |
|
1451 if (NULL == init_value) {return NULL;} // this is some datatype for which no initial value exists! Do nothing and return. |
1418 init_value->accept(*this); // necessary when handling default initial values, that were not constant folded in the call type_decl->accept(*this) |
1452 init_value->accept(*this); // necessary when handling default initial values, that were not constant folded in the call type_decl->accept(*this) |
1419 |
1453 |
1420 list_c *list = dynamic_cast<list_c *>(var_list); |
1454 list_c *list = dynamic_cast<list_c *>(var_list); |
1421 if (NULL == list) ERROR; |
1455 if (NULL == list) ERROR; |
1422 for (int i = 0; i < list->n; i++) { |
1456 for (int i = 0; i < list->n; i++) { |
1468 |
1502 |
1469 /* fb_name_list ':' function_block_type_name ASSIGN structure_initialization */ |
1503 /* fb_name_list ':' function_block_type_name ASSIGN structure_initialization */ |
1470 //SYM_REF2(fb_name_decl_c, fb_name_list, fb_spec_init) |
1504 //SYM_REF2(fb_name_decl_c, fb_name_list, fb_spec_init) |
1471 void *constant_propagation_c::visit(fb_name_decl_c *symbol) { |
1505 void *constant_propagation_c::visit(fb_name_decl_c *symbol) { |
1472 /* A FB has been instantiated inside the POU currently being analysed. We must therefore visit this FB's type declaration |
1506 /* A FB has been instantiated inside the POU currently being analysed. We must therefore visit this FB's type declaration |
1473 * and give a chance of the VAR_EXTERNs in that FB to get the const values from the global variables currently in scope! |
1507 * and give the VAR_EXTERNs in that FB a chance to get the const values from the global variables currently in scope! |
1474 */ |
1508 */ |
1475 /* find the declaration (i.e. the datatype) of the FB being instantiated */ |
1509 // NOTE: The generic handle_var_list_decl() can handle the above situation, so we simply call it! |
1476 // NOTE: we do not use symbol->datatype so this const propagation algorithm will not depend on the fill/narrow datatypes algorithm! |
1510 // NOTE: The handle_var_list_decl() should not be needing the fb_name_list to do the above, so we call |
1477 symbol_c *fb_type_name = spec_init_sperator_c::get_spec(symbol->fb_spec_init); |
1511 // it with NULL to highlight this fact! |
1478 function_block_type_symtable_t::iterator itr = function_block_type_symtable.find(fb_type_name); |
1512 return handle_var_list_decl(NULL, symbol->fb_spec_init); |
1479 if (itr == function_block_type_symtable.end()) ERROR; // syntax parsing should not allow this! |
|
1480 function_block_declaration_c *fb_type = itr->second; |
|
1481 if (NULL == fb_type) ERROR; // syntax parsing should not allow this! |
|
1482 // TODO: detect whether we are already currently visiting this exact same FB declaration (possible with -p option), so we do not get into an infinite loop!! |
|
1483 fb_type->accept(*this); |
|
1484 return NULL; |
|
1485 } |
1513 } |
1486 |
1514 |
1487 |
1515 |
1488 /* fb_name_list ',' fb_name */ |
1516 /* fb_name_list ',' fb_name */ |
1489 //SYM_LIST(fb_name_list_c) // Not needed! |
1517 //SYM_LIST(fb_name_list_c) // Not needed! |