1239 : constant_folding_c(symbol) { |
1239 : constant_folding_c(symbol) { |
1240 current_resource = NULL; |
1240 current_resource = NULL; |
1241 current_configuration = NULL; |
1241 current_configuration = NULL; |
1242 fixed_init_value_ = false; |
1242 fixed_init_value_ = false; |
1243 function_pou_ = false; |
1243 function_pou_ = false; |
1244 } |
1244 values = NULL; |
|
1245 } |
1245 |
1246 |
1246 |
1247 |
1247 constant_propagation_c::~constant_propagation_c(void) {} |
1248 constant_propagation_c::~constant_propagation_c(void) {} |
1248 |
1249 |
1249 |
1250 |
1383 /* B 1.4 - Variables */ |
1384 /* B 1.4 - Variables */ |
1384 /*********************/ |
1385 /*********************/ |
1385 #if DO_CONSTANT_PROPAGATION__ |
1386 #if DO_CONSTANT_PROPAGATION__ |
1386 void *constant_propagation_c::visit(symbolic_variable_c *symbol) { |
1387 void *constant_propagation_c::visit(symbolic_variable_c *symbol) { |
1387 std::string varName = get_var_name_c::get_name(symbol->var_name)->value; |
1388 std::string varName = get_var_name_c::get_name(symbol->var_name)->value; |
1388 if (values.count(varName) > 0) |
1389 if (values->count(varName) > 0) |
1389 symbol->const_value = values[varName]; |
1390 symbol->const_value = (*values)[varName]; |
1390 return NULL; |
1391 return NULL; |
1391 } |
1392 } |
1392 #endif // DO_CONSTANT_PROPAGATION__ |
1393 #endif // DO_CONSTANT_PROPAGATION__ |
1393 |
1394 |
1394 void *constant_propagation_c::visit(symbolic_constant_c *symbol) { |
1395 void *constant_propagation_c::visit(symbolic_constant_c *symbol) { |
1395 std::string varName = get_var_name_c::get_name(symbol->var_name)->value; |
1396 std::string varName = get_var_name_c::get_name(symbol->var_name)->value; |
1396 if (values.count(varName) > 0) |
1397 if (values->count(varName) > 0) |
1397 symbol->const_value = values[varName]; |
1398 symbol->const_value = (*values)[varName]; |
1398 return NULL; |
1399 return NULL; |
1399 } |
1400 } |
1400 |
1401 |
1401 |
1402 |
1402 /******************************************/ |
1403 /******************************************/ |
1408 var_list->accept(*this); |
1409 var_list->accept(*this); |
1409 fixed_init_value_ = false; |
1410 fixed_init_value_ = false; |
1410 return NULL; |
1411 return NULL; |
1411 } |
1412 } |
1412 |
1413 |
1413 void *constant_propagation_c::handle_var_list_decl(symbol_c *var_list, symbol_c *type_decl) { |
1414 void *constant_propagation_c::handle_var_list_decl(symbol_c *var_list, symbol_c *type_decl, bool is_global_var) { |
1414 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) |
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) |
1415 symbol_c *init_value = type_initial_value_c::get(type_decl); |
1416 symbol_c *init_value = type_initial_value_c::get(type_decl); |
1416 if (NULL == init_value) {return NULL;} // this is probably a FB datatype, for which no initial value exists! Do nothing and return. |
1417 if (NULL == init_value) {return NULL;} // this is probably a FB datatype, for which no initial value exists! Do nothing and return. |
1417 init_value->accept(*this); // necessary when handling default initial values, that were not constant folded in the call type_decl->accept(*this) |
1418 init_value->accept(*this); // necessary when handling default initial values, that were not constant folded in the call type_decl->accept(*this) |
1418 |
1419 |
1426 // debug_c::print(list->elements[i]); |
1427 // debug_c::print(list->elements[i]); |
1427 ERROR; |
1428 ERROR; |
1428 } |
1429 } |
1429 list->elements[i]->const_value = init_value->const_value; |
1430 list->elements[i]->const_value = init_value->const_value; |
1430 if (fixed_init_value_) { |
1431 if (fixed_init_value_) { |
1431 values[var_name->value] = init_value->const_value; |
1432 (*values)[var_name->value] = init_value->const_value; |
|
1433 if (is_global_var) |
|
1434 // also store it in the var_global_values map!! |
|
1435 // Notice that global variables are also placed in the values map!! |
|
1436 var_global_values[var_name->value] = init_value->const_value; |
1432 } |
1437 } |
1433 } |
1438 } |
1434 return NULL; |
1439 return NULL; |
1435 } |
1440 } |
1436 |
1441 |
1460 |
1465 |
1461 /* var1_list ':' initialized_structure */ |
1466 /* var1_list ':' initialized_structure */ |
1462 //SYM_REF2(structured_var_init_decl_c, var1_list, initialized_structure) // We do not yet handle structures! |
1467 //SYM_REF2(structured_var_init_decl_c, var1_list, initialized_structure) // We do not yet handle structures! |
1463 |
1468 |
1464 /* fb_name_list ':' function_block_type_name ASSIGN structure_initialization */ |
1469 /* fb_name_list ':' function_block_type_name ASSIGN structure_initialization */ |
1465 //SYM_REF2(fb_name_decl_c, fb_name_list, fb_spec_init) // We do not yet handle FBs! |
1470 //SYM_REF2(fb_name_decl_c, fb_name_list, fb_spec_init) |
|
1471 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 |
|
1473 * and give a chance of the VAR_EXTERNs in that FB to get the const values from the global variables currently in scope! |
|
1474 */ |
|
1475 /* find the declaration (i.e. the datatype) of the FB being instantiated */ |
|
1476 // NOTE: we do not use symbol->datatype so this const propagation algorithm will not depend on the fill/narrow datatypes algorithm! |
|
1477 symbol_c *fb_type_name = spec_init_sperator_c::get_spec(symbol->fb_spec_init); |
|
1478 function_block_type_symtable_t::iterator itr = function_block_type_symtable.find(fb_type_name); |
|
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 } |
|
1486 |
1466 |
1487 |
1467 /* fb_name_list ',' fb_name */ |
1488 /* fb_name_list ',' fb_name */ |
1468 //SYM_LIST(fb_name_list_c) // Not needed! |
1489 //SYM_LIST(fb_name_list_c) // Not needed! |
1469 |
1490 |
1470 /* VAR_INPUT [option] input_declaration_list END_VAR */ |
1491 /* VAR_INPUT [option] input_declaration_list END_VAR */ |
1563 symbol->specification->const_value = var_global_values[get_var_name_c::get_name(symbol->global_var_name)->value]; |
1584 symbol->specification->const_value = var_global_values[get_var_name_c::get_name(symbol->global_var_name)->value]; |
1564 } |
1585 } |
1565 |
1586 |
1566 symbol->global_var_name->const_value = symbol->specification->const_value; |
1587 symbol->global_var_name->const_value = symbol->specification->const_value; |
1567 if (fixed_init_value_) { |
1588 if (fixed_init_value_) { |
1568 // values[symbol->global_var_name->get_value()] = symbol->specification->const_value; |
1589 // (*values)[symbol->global_var_name->get_value()] = symbol->specification->const_value; |
1569 values[get_var_name_c::get_name(symbol->global_var_name)->value] = symbol->specification->const_value; |
1590 (*values)[get_var_name_c::get_name(symbol->global_var_name)->value] = symbol->specification->const_value; |
1570 } |
1591 } |
1571 // 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) |
1592 // 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) |
1572 symbol->specification->accept(*this); // should never get to change the const_value of the symbol->specification symbol (only its children!). |
1593 symbol->specification->accept(*this); // should never get to change the const_value of the symbol->specification symbol (only its children!). |
1573 return NULL; |
1594 return NULL; |
1574 } |
1595 } |
1613 * if it is a global_var_spec_c we will create a temporary list so we can call that method! |
1634 * if it is a global_var_spec_c we will create a temporary list so we can call that method! |
1614 */ |
1635 */ |
1615 global_var_spec_c *var_spec = dynamic_cast<global_var_spec_c *>(symbol->global_var_spec); |
1636 global_var_spec_c *var_spec = dynamic_cast<global_var_spec_c *>(symbol->global_var_spec); |
1616 if (NULL == var_spec) { |
1637 if (NULL == var_spec) { |
1617 // global_var_spec is a global_var_list_c |
1638 // global_var_spec is a global_var_list_c |
1618 return handle_var_list_decl(symbol->global_var_spec, symbol->type_specification); |
1639 return handle_var_list_decl(symbol->global_var_spec, symbol->type_specification, true /* is global */); |
1619 } else { |
1640 } else { |
1620 global_var_list_c var_list; |
1641 global_var_list_c var_list; |
1621 var_list.add_element(var_spec->global_var_name); |
1642 var_list.add_element(var_spec->global_var_name); |
1622 return handle_var_list_decl(&var_list, symbol->type_specification); |
1643 return handle_var_list_decl(&var_list, symbol->type_specification, true /* is global */); |
1623 } |
1644 } |
1624 } |
1645 } |
1625 |
1646 |
1626 |
1647 |
1627 /*| global_var_name location */ |
1648 /*| global_var_name location */ |
1677 /* B 1.5.1 - Functions */ |
1698 /* B 1.5.1 - Functions */ |
1678 /***********************/ |
1699 /***********************/ |
1679 /* 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 */ |
1700 /* 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 */ |
1680 //SYM_REF4(function_declaration_c, derived_function_name, type_name, var_declarations_list, function_body, enumvalue_symtable_t enumvalue_symtable;) |
1701 //SYM_REF4(function_declaration_c, derived_function_name, type_name, var_declarations_list, function_body, enumvalue_symtable_t enumvalue_symtable;) |
1681 void *constant_propagation_c::visit(function_declaration_c *symbol) { |
1702 void *constant_propagation_c::visit(function_declaration_c *symbol) { |
1682 values.clear(); /* Clear global map */ |
1703 map_values_t local_values, *prev_pou_values; |
|
1704 prev_pou_values = values; // store the current values map of whoever called this Function (a program, configuration, or resource) |
|
1705 values = &local_values; |
|
1706 var_global_values.push(); /* Create inner scope - Not really needed, but do it just to be consistent. */ |
|
1707 |
1683 /* Add initial value of all declared variables into Values map. */ |
1708 /* Add initial value of all declared variables into Values map. */ |
1684 function_pou_ = true; |
1709 function_pou_ = true; |
1685 symbol->var_declarations_list->accept(*this); |
1710 symbol->var_declarations_list->accept(*this); |
1686 function_pou_ = false; |
1711 function_pou_ = false; |
1687 symbol->function_body->accept(*this); |
1712 symbol->function_body->accept(*this); |
|
1713 |
|
1714 var_global_values.pop(); /* Delete inner scope */ |
|
1715 values = prev_pou_values; |
1688 return NULL; |
1716 return NULL; |
1689 } |
1717 } |
1690 |
1718 |
1691 |
1719 |
1692 /* intermediate helper symbol for |
1720 /* intermediate helper symbol for |
1710 /*****************************/ |
1738 /*****************************/ |
1711 /* FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */ |
1739 /* FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */ |
1712 /* 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 */ |
1740 /* 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 */ |
1713 //SYM_REF3(function_block_declaration_c, fblock_name, var_declarations, fblock_body, enumvalue_symtable_t enumvalue_symtable;) |
1741 //SYM_REF3(function_block_declaration_c, fblock_name, var_declarations, fblock_body, enumvalue_symtable_t enumvalue_symtable;) |
1714 void *constant_propagation_c::visit(function_block_declaration_c *symbol) { |
1742 void *constant_propagation_c::visit(function_block_declaration_c *symbol) { |
1715 values.clear(); /* Clear global map */ |
1743 map_values_t local_values, *prev_pou_values; |
|
1744 prev_pou_values = values; // store the current values map of whoever instantited this FB (a program, configuration, or resource) |
|
1745 values = &local_values; |
|
1746 var_global_values.push(); /* Create inner scope */ |
|
1747 |
1716 /* Add initial value of all declared variables into Values map. */ |
1748 /* Add initial value of all declared variables into Values map. */ |
1717 function_pou_ = false; |
1749 function_pou_ = false; |
1718 symbol->var_declarations->accept(*this); |
1750 symbol->var_declarations->accept(*this); |
1719 symbol->fblock_body->accept(*this); |
1751 symbol->fblock_body->accept(*this); |
|
1752 |
|
1753 var_global_values.pop(); /* Delete inner scope */ |
|
1754 values = prev_pou_values; |
1720 return NULL; |
1755 return NULL; |
1721 } |
1756 } |
1722 |
1757 |
1723 /* VAR_TEMP temp_var_decl_list END_VAR */ |
1758 /* VAR_TEMP temp_var_decl_list END_VAR */ |
1724 // SYM_REF1(temp_var_decls_c, var_decl_list) |
1759 // SYM_REF1(temp_var_decls_c, var_decl_list) |
1737 /* B 1.5.3 - Programs */ |
1772 /* B 1.5.3 - Programs */ |
1738 /**********************/ |
1773 /**********************/ |
1739 /* PROGRAM program_type_name program_var_declarations_list function_block_body END_PROGRAM */ |
1774 /* PROGRAM program_type_name program_var_declarations_list function_block_body END_PROGRAM */ |
1740 //SYM_REF3(program_declaration_c, program_type_name, var_declarations, function_block_body, enumvalue_symtable_t enumvalue_symtable;) |
1775 //SYM_REF3(program_declaration_c, program_type_name, var_declarations, function_block_body, enumvalue_symtable_t enumvalue_symtable;) |
1741 void *constant_propagation_c::visit(program_declaration_c *symbol) { |
1776 void *constant_propagation_c::visit(program_declaration_c *symbol) { |
1742 values.clear(); /* Clear global map */ |
1777 map_values_t local_values, *prev_pou_values; |
|
1778 prev_pou_values = values; // store the current values map of whoever instantited this Program (a configuration, or resource) |
|
1779 values = &local_values; |
|
1780 var_global_values.push(); /* Create inner scope */ |
|
1781 |
1743 /* Add initial value of all declared variables into Values map. */ |
1782 /* Add initial value of all declared variables into Values map. */ |
1744 function_pou_ = false; |
1783 function_pou_ = false; |
1745 symbol->var_declarations->accept(*this); |
1784 symbol->var_declarations->accept(*this); |
1746 symbol->function_block_body->accept(*this); |
1785 symbol->function_block_body->accept(*this); |
|
1786 |
|
1787 var_global_values.pop(); /* Delete inner scope */ |
|
1788 values = prev_pou_values; |
1747 return NULL; |
1789 return NULL; |
1748 } |
1790 } |
1749 |
1791 |
1750 |
1792 |
1751 /********************************/ |
1793 /********************************/ |
1762 */ |
1804 */ |
1763 /* 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 */ |
1805 /* 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 */ |
1764 // SYM_REF5(configuration_declaration_c, configuration_name, global_var_declarations, resource_declarations, access_declarations, instance_specific_initializations, |
1806 // SYM_REF5(configuration_declaration_c, configuration_name, global_var_declarations, resource_declarations, access_declarations, instance_specific_initializations, |
1765 // enumvalue_symtable_t enumvalue_symtable; localvar_symbmap_t localvar_symbmap; localvar_symbvec_t localvar_symbvec;) |
1807 // enumvalue_symtable_t enumvalue_symtable; localvar_symbmap_t localvar_symbmap; localvar_symbvec_t localvar_symbvec;) |
1766 void *constant_propagation_c::visit(configuration_declaration_c *symbol) { |
1808 void *constant_propagation_c::visit(configuration_declaration_c *symbol) { |
1767 values.clear(); /* Clear global map */ |
1809 map_values_t local_values; |
|
1810 values = &local_values; |
|
1811 var_global_values.clear(); /* Clear global variables map */ |
1768 |
1812 |
1769 /* Add initial value of all declared variables into Values map. */ |
1813 /* Add initial value of all declared variables into Values map. */ |
1770 function_pou_ = false; |
1814 function_pou_ = false; |
1771 current_configuration = symbol; |
1815 current_configuration = symbol; |
1772 iterator_visitor_c::visit(symbol); // let the base iterator class handle the rest (basically iterate through the whole configuration and do the constant folding! |
1816 iterator_visitor_c::visit(symbol); // let the base iterator class handle the rest (basically iterate through the whole configuration and do the constant folding! |
1773 current_configuration = NULL; |
1817 current_configuration = NULL; |
|
1818 |
|
1819 values = NULL; |
1774 return NULL; |
1820 return NULL; |
1775 } |
1821 } |
1776 |
1822 |
1777 |
1823 |
1778 /* helper symbol for configuration_declaration */ |
1824 /* helper symbol for configuration_declaration */ |
1786 */ |
1832 */ |
1787 /* 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 */ |
1833 /* 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 */ |
1788 // SYM_REF4(resource_declaration_c, resource_name, resource_type_name, global_var_declarations, resource_declaration, |
1834 // SYM_REF4(resource_declaration_c, resource_name, resource_type_name, global_var_declarations, resource_declaration, |
1789 // enumvalue_symtable_t enumvalue_symtable; localvar_symbmap_t localvar_symbmap; localvar_symbvec_t localvar_symbvec;) |
1835 // enumvalue_symtable_t enumvalue_symtable; localvar_symbmap_t localvar_symbmap; localvar_symbvec_t localvar_symbvec;) |
1790 void *constant_propagation_c::visit(resource_declaration_c *symbol) { |
1836 void *constant_propagation_c::visit(resource_declaration_c *symbol) { |
1791 values.push(); /* Create inner scope */ |
1837 var_global_values.push(); /* Create inner scope */ |
|
1838 values->push(); /* Create inner scope */ |
1792 |
1839 |
1793 /* Add initial value of all declared variables into Values map. */ |
1840 /* Add initial value of all declared variables into Values map. */ |
1794 function_pou_ = false; |
1841 function_pou_ = false; |
1795 symbol->global_var_declarations->accept(*this); |
1842 symbol->global_var_declarations->accept(*this); |
1796 |
1843 |
1797 var_global_values = values; |
|
1798 values.clear(); |
|
1799 current_resource = symbol; |
1844 current_resource = symbol; |
1800 symbol->resource_declaration->accept(*this); |
1845 symbol->resource_declaration->accept(*this); |
1801 current_resource = NULL; |
1846 current_resource = NULL; |
1802 values = var_global_values; |
|
1803 // iterator_visitor_c::visit(symbol); // let the base iterator class handle the rest (basically iterate through the whole configuration and do the constant folding! |
1847 // iterator_visitor_c::visit(symbol); // let the base iterator class handle the rest (basically iterate through the whole configuration and do the constant folding! |
1804 |
1848 |
1805 values.pop(); /* Delete inner scope */ |
1849 var_global_values.pop(); /* Delete inner scope */ |
|
1850 values->pop(); /* Delete inner scope */ |
1806 return NULL; |
1851 return NULL; |
1807 } |
1852 } |
1808 |
1853 |
1809 |
1854 |
1810 |
1855 |
1913 std::string varName; |
1958 std::string varName; |
1914 |
1959 |
1915 symbol->r_exp->accept(*this); |
1960 symbol->r_exp->accept(*this); |
1916 symbol->l_exp->accept(*this); // if the lvalue has an array, do contant folding of the array indexes! |
1961 symbol->l_exp->accept(*this); // if the lvalue has an array, do contant folding of the array indexes! |
1917 symbol->l_exp->const_value = symbol->r_exp->const_value; |
1962 symbol->l_exp->const_value = symbol->r_exp->const_value; |
1918 values[get_var_name_c::get_name(symbol->l_exp)->value] = symbol->l_exp->const_value; |
1963 (*values)[get_var_name_c::get_name(symbol->l_exp)->value] = symbol->l_exp->const_value; |
1919 return NULL; |
1964 return NULL; |
1920 } |
1965 } |
1921 |
1966 |
1922 /********************************/ |
1967 /********************************/ |
1923 /* B 3.2.3 Selection Statements */ |
1968 /* B 3.2.3 Selection Statements */ |
1955 map_values_t values_statement_result; |
2000 map_values_t values_statement_result; |
1956 |
2001 |
1957 values_incoming = values; /* save incoming status */ |
2002 values_incoming = values; /* save incoming status */ |
1958 symbol->beg_expression->accept(*this); |
2003 symbol->beg_expression->accept(*this); |
1959 symbol->end_expression->accept(*this); |
2004 symbol->end_expression->accept(*this); |
1960 values[get_var_name_c::get_name(symbol->control_variable)->value]._int64.status = const_value_c::cs_non_const; |
2005 (*values)[get_var_name_c::get_name(symbol->control_variable)->value]._int64.status = const_value_c::cs_non_const; |
1961 |
2006 |
1962 /* Optimize dead code */ |
2007 /* Optimize dead code */ |
1963 if (NULL != symbol->by_expression) { |
2008 if (NULL != symbol->by_expression) { |
1964 symbol->by_expression->accept(*this); |
2009 symbol->by_expression->accept(*this); |
1965 if (VALID_CVALUE(int64, symbol->by_expression ) && GET_CVALUE(int64, symbol->by_expression ) > 0 && |
2010 if (VALID_CVALUE(int64, symbol->by_expression ) && GET_CVALUE(int64, symbol->by_expression ) > 0 && |