Do constant propagation inside Configurations and Resources (required for support of extension: array [1..max] OF int); (Resources is still buggy)
authormjsousa
Fri, 26 Dec 2014 08:09:34 +0000
changeset 969 706a152731ab
parent 968 649e03abbfc1
child 970 0ede7ca157e2
Do constant propagation inside Configurations and Resources (required for support of extension: array [1..max] OF int); (Resources is still buggy)
stage3/constant_folding.cc
stage3/constant_folding.hh
--- a/stage3/constant_folding.cc	Thu Dec 25 08:40:15 2014 +0000
+++ b/stage3/constant_folding.cc	Fri Dec 26 08:09:34 2014 +0000
@@ -235,9 +235,6 @@
 		}\
 }
 
-typedef std::map <std::string, const_value_c> map_values_t;
-
-static map_values_t values;
 
 
 
@@ -726,9 +723,9 @@
 	return NULL;
 }
 
-static map_values_t inner_left_join_values(map_values_t m1, map_values_t m2) {
-	map_values_t::const_iterator itr;
-	map_values_t ret;
+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) {
+	constant_folding_c::map_values_t::const_iterator itr;
+	constant_folding_c::map_values_t ret;
 
 	itr = m1.begin();
 	for ( ; itr != m1.end(); ++itr) {
@@ -1171,7 +1168,7 @@
 /*  global_var_name ':' (simple_specification|subrange_specification|enumerated_specification|array_specification|prev_declared_structure_type_name|function_block_type_name */
 //SYM_REF2(external_declaration_c, global_var_name, specification)
 void *constant_folding_c::visit(external_declaration_c *symbol) {
-  // Note that specification->const_value will have been set by handle_var_extern_global_pair, which is called from declaration_check_c
+  // Note that specification->const_value will have been set by handle_var_extern_global_pair(), which is called from declaration_check_c
   symbol->global_var_name->const_value = symbol->specification->const_value;
   if (fixed_init_value_) {
     std::string varName = get_var_name_c::get_name(symbol->global_var_name)->value;
@@ -1182,33 +1179,70 @@
   return NULL;
 }
 
-/* Visitors related to GLOBAL variables are not really needed, 
- * as they are already handled by handle_var_extern_global_pair, which is called from declaration_check_c 
- * 
+/* NOTE that the constant folding of GLOBAL variables is already handled by handle_var_extern_global_pair, which 
+ * is called from declaration_check_c,
  * This is done like this because we need to know the pairing of external<->global variables to get the cvalue
  * from the global variable. Since the external<->global pairing information is available in the declaration_check_c,
  * we have that class call the constant_folding_c::handle_var_extern_global_pair(), which will actually do the 
  * constant folding of the global and the external variable declarations!
  */
+/* NOTE: The constant propagation portion of this algorithm must still be done here!!
+ * Even though the constant folding of GLOBAL variables are already handled by handle_var_extern_global_pair(),
+ * we must still visit them here, since when doing constant propagation of a Configuration or a Resource we need the
+ * values of constant variables to be placed in the values[] map, as these same variables may be used to declare
+ * arrays of a variable size
+ *    VAR_GLOBAL CONSTANT max     : INT := 42;             END_VAR
+ *    VAR_GLOBAL          array_v : ARRAY [1..max] of INT; END_VAR  <---- NOTE the use of 'max' in the subrange!
+ */
 /*| VAR_GLOBAL [CONSTANT|RETAIN] global_var_decl_list END_VAR */
 /* option -> may be NULL ! */
 // SYM_REF2(global_var_declarations_c, option, global_var_decl_list)
+/* Note that calling handle_var_decl() will result in doing constant folding of literals (of datatype initial values)
+ * that were already constant folded by the method handle_var_extern_global_pair()
+ * Nevertheless, since constant folding is idem-potent, it is simpler to just call handle_var_decl() instead
+ * of writing some code specific for this situation!
+ */
+void *constant_folding_c::visit(global_var_declarations_c *symbol) {return handle_var_decl(symbol->global_var_decl_list, is_constant(symbol->option));}
+
+
 /* helper symbol for global_var_declarations */
 /*| global_var_decl_list global_var_decl ';' */
 // SYM_LIST(global_var_decl_list_c)
+// void *constant_folding_c::visit(global_var_decl_list_c *symbol) {} // Not needed: we inherit from iterator_c
+
 /*| global_var_spec ':' [located_var_spec_init|function_block_type_name] */
 /* type_specification ->may be NULL ! */
 //SYM_REF2(global_var_decl_c, global_var_spec, type_specification)
+void *constant_folding_c::visit(global_var_decl_c *symbol) {
+  /* global_var_spec may be either a global_var_spec_c or a global_var_list_c.
+   * Since we already have a nice method that handles var lists (handle_var_list_decl() )
+   * if it is a global_var_spec_c we will create a temporary list so we can call that method!
+   */
+  global_var_spec_c *var_spec = dynamic_cast<global_var_spec_c *>(symbol->global_var_spec);
+  if (NULL == var_spec) {
+    // global_var_spec is a global_var_list_c
+    return handle_var_list_decl(symbol->global_var_spec, symbol->type_specification);
+  } else {
+    global_var_list_c var_list;
+    var_list.add_element(var_spec->global_var_name);
+    return handle_var_list_decl(&var_list, symbol->type_specification);
+  }
+}
+
+
 /*| global_var_name location */
-//SYM_REF2(global_var_spec_c, global_var_name, location)
+//SYM_REF2(global_var_spec_c, global_var_name, location)              // Not needed!
+
 /*  AT direct_variable */
-//SYM_REF1(location_c, direct_variable)
+//SYM_REF1(location_c, direct_variable)                               // Not needed!
+
 /*| global_var_list ',' global_var_name */
-//SYM_LIST(global_var_list_c)
+//SYM_LIST(global_var_list_c)                                         // Not needed!
 
 
 #if 0  
 // TODO
+// We do not do constant folding of strings yet, so there is no need to implement this now!
 /*  var1_list ':' single_byte_string_spec */
 SYM_REF2(single_byte_string_var_declaration_c, var1_list, single_byte_string_spec)
 /*  STRING ['[' integer ']'] [ASSIGN single_byte_character_string] */
@@ -1320,6 +1354,93 @@
 }
 
 
+/********************************/
+/* B 1.7 Configuration elements */
+/********************************/
+
+/*
+CONFIGURATION configuration_name
+   optional_global_var_declarations
+   (resource_declaration_list | single_resource_declaration)
+   optional_access_declarations
+   optional_instance_specific_initializations
+END_CONFIGURATION
+*/
+/* 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 */
+// SYM_REF5(configuration_declaration_c, configuration_name, global_var_declarations, resource_declarations, access_declarations, instance_specific_initializations, 
+//          enumvalue_symtable_t enumvalue_symtable; localvar_symbmap_t localvar_symbmap; localvar_symbvec_t localvar_symbvec;)
+void *constant_folding_c::visit(configuration_declaration_c *symbol) {
+	values.clear(); /* Clear global map */
+	/* Add initial value of all declared variables into Values map. */
+	function_pou_ = false;
+	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!
+}
+
+
+/* helper symbol for configuration_declaration */
+// SYM_LIST(resource_declaration_list_c)           // Not needed: we inherit from iterator_c
+
+/*
+RESOURCE resource_name ON resource_type_name
+   optional_global_var_declarations
+   single_resource_declaration
+END_RESOURCE
+*/
+/* 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 */
+// SYM_REF4(resource_declaration_c, resource_name, resource_type_name, global_var_declarations, resource_declaration, 
+//          enumvalue_symtable_t enumvalue_symtable; localvar_symbmap_t localvar_symbmap; localvar_symbvec_t localvar_symbvec;)
+void *constant_folding_c::visit(resource_declaration_c *symbol) {
+	values.clear(); /* Clear global map */
+	/* Add initial value of all declared variables into Values map. */
+	function_pou_ = false;
+	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!
+}
+
+
+
+/* task_configuration_list program_configuration_list */
+// SYM_REF2(single_resource_declaration_c, task_configuration_list, program_configuration_list)
+/* helper symbol for single_resource_declaration */
+// SYM_LIST(task_configuration_list_c)
+/* helper symbol for single_resource_declaration */
+// SYM_LIST(program_configuration_list_c)
+/* helper symbol for: (access_path, instance_specific_init) */
+// SYM_LIST(any_fb_name_list_c)
+/*  [resource_name '.'] global_var_name ['.' structure_element_name] */
+// SYM_REF3(global_var_reference_c, resource_name, global_var_name, structure_element_name)
+/*  prev_declared_program_name '.' symbolic_variable */
+// SYM_REF2(program_output_reference_c, program_name, symbolic_variable)
+/*  TASK task_name task_initialization */
+// SYM_REF2(task_configuration_c, task_name, task_initialization)
+/*  '(' [SINGLE ASSIGN data_source ','] [INTERVAL ASSIGN data_source ','] PRIORITY ASSIGN integer ')' */
+// SYM_REF3(task_initialization_c, single_data_source, interval_data_source, priority_data_source)
+/*  PROGRAM [RETAIN | NON_RETAIN] program_name [WITH task_name] ':' program_type_name ['(' prog_conf_elements ')'] */
+/* NOTE: The parameter 'called_prog_declaration'is used to pass data between stage 3 and stage4 */
+// SYM_REF5(program_configuration_c, retain_option, program_name, task_name, program_type_name, prog_conf_elements,
+//          symbol_c *called_prog_declaration;)
+/* prog_conf_elements ',' prog_conf_element */
+// SYM_LIST(prog_conf_elements_c)
+/*  fb_name WITH task_name */
+// SYM_REF2(fb_task_c, fb_name, task_name)
+/*  any_symbolic_variable ASSIGN prog_data_source */
+// SYM_REF2(prog_cnxn_assign_c, symbolic_variable, prog_data_source)
+/* any_symbolic_variable SENDTO data_sink */
+// SYM_REF2(prog_cnxn_sendto_c, symbolic_variable, data_sink)
+/* VAR_CONFIG instance_specific_init_list END_VAR */
+// SYM_REF1(instance_specific_initializations_c, instance_specific_init_list)
+/* helper symbol for instance_specific_initializations */
+// SYM_LIST(instance_specific_init_list_c)
+/* resource_name '.' program_name '.' {fb_name '.'}
+    ((variable_name [location] ':' located_var_spec_init) | (fb_name ':' fb_initialization))
+*/
+// SYM_REF6(instance_specific_init_c, resource_name, program_name, any_fb_name_list, variable_name, location, initialization)
+/* helper symbol for instance_specific_init */
+/* function_block_type_name ':=' structure_initialization */
+// SYM_REF2(fb_initialization_c, function_block_type_name, structure_initialization)
+
+
+
+
 /****************************************/
 /* B.2 - Language IL (Instruction List) */
 /****************************************/
--- a/stage3/constant_folding.hh	Thu Dec 25 08:40:15 2014 +0000
+++ b/stage3/constant_folding.hh	Fri Dec 26 08:09:34 2014 +0000
@@ -61,21 +61,25 @@
     /* the current IL operand being analyzed */
     symbol_c *il_operand;
 
+
+
   public:
-	constant_folding_c(symbol_c *symbol = NULL);
-	virtual ~constant_folding_c(void);
-	int get_error_count();
-	int 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);
+    constant_folding_c(symbol_c *symbol = NULL);
+    virtual ~constant_folding_c(void);
+    int get_error_count();
+    int 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);
+    typedef std::map <std::string, const_value_c> map_values_t;
   private:
-	void *handle_var_list_decl(symbol_c *var_list, symbol_c *type_decl);
-	void *handle_var_decl     (symbol_c *var_list, bool fixed_init_value);
-	// Flag to indicate whether the variables in the variable declaration list will always have a fixed value when the POU is executed!
-	// VAR CONSTANT ... END_VAR will always be true
-	// VAR          ... END_VAR will always be true for functions (who initialise local variables every time they are called), but false for FBs and PROGRAMS
-	bool fixed_init_value_; 
-	bool function_pou_;
-	bool is_constant(symbol_c *option);
-	bool is_retain  (symbol_c *option);
+    map_values_t values;
+    void *handle_var_list_decl(symbol_c *var_list, symbol_c *type_decl);
+    void *handle_var_decl     (symbol_c *var_list, bool fixed_init_value);
+    // Flag to indicate whether the variables in the variable declaration list will always have a fixed value when the POU is executed!
+    // VAR CONSTANT ... END_VAR will always be true
+    // VAR          ... END_VAR will always be true for functions (who initialise local variables every time they are called), but false for FBs and PROGRAMS
+    bool fixed_init_value_; 
+    bool function_pou_;
+    bool is_constant(symbol_c *option);
+    bool is_retain  (symbol_c *option);
 
 
   public:
@@ -124,14 +128,16 @@
     /******************************************/
     /* B 1.4.3 - Declaration & Initialisation */
     /******************************************/
-    void *visit(var1_init_decl_c             *symbol);
     void *visit(        input_declarations_c *symbol);
     void *visit(       output_declarations_c *symbol);
     void *visit( input_output_declarations_c *symbol);
     void *visit(          var_declarations_c *symbol);
     void *visit(retentive_var_declarations_c *symbol);
     void *visit( external_var_declarations_c *symbol);
-    void *visit(external_declaration_c       *symbol);
+    void *visit(   global_var_declarations_c *symbol);
+    void *visit(  external_declaration_c     *symbol);
+    void *visit(global_var_decl_c            *symbol);
+    void *visit( var1_init_decl_c            *symbol);
 
     /**************************************/
     /* B.1.5 - Program organization units */
@@ -152,7 +158,13 @@
     /**********************/
     /* B 1.5.3 - Programs */
     /**********************/
-    void *visit(program_declaration_c *symbol);
+    void *visit(       program_declaration_c *symbol);
+
+    /********************************/
+    /* B 1.7 Configuration elements */
+    /********************************/
+    void *visit( configuration_declaration_c *symbol);
+    void *visit(      resource_declaration_c *symbol);
 
 
     /****************************************/