stage3/constant_folding.cc
changeset 988 3b12a6cf9fbd
parent 985 837c6532a9b8
child 989 d4f8931d80cd
equal deleted inserted replaced
987:562b67922966 988:3b12a6cf9fbd
  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 &&