merge
authorMario de Sousa <msousa@fe.up.pt>
Thu, 27 Dec 2012 15:04:58 +0000
changeset 777 e74a882c8d22
parent 776 96a1199d0739 (diff)
parent 772 30e5193cc19a (current diff)
child 778 44e02a88f1e7
merge
--- a/absyntax/absyntax.hh	Sun Dec 02 18:20:02 2012 +0100
+++ b/absyntax/absyntax.hh	Thu Dec 27 15:04:58 2012 +0000
@@ -143,15 +143,15 @@
      * having more than one entry filled in!
      */
     typedef enum { cs_undefined,   /* not defined/not yet evaluated --> const_value is not valid! */
-                   cs_non_const,   /* we have deternmined that expression is not a const value --> const_value is not valid! */
+                   cs_non_const,   /* we have determined that expression is not a const value --> const_value is not valid! */
                    cs_const_value, /* const value is valid */
                    cs_overflow     /* result produced overflow or underflow --> const_value is not valid! */
                  } const_status_t;
  
-    typedef struct {const_status_t status;  real64_t  value; } const_value_real64_t;
-    typedef struct {const_status_t status;   int64_t  value; } const_value_int64_t;
-    typedef struct {const_status_t status;  uint64_t  value; } const_value_uint64_t;
-    typedef struct {const_status_t status;      bool  value; } const_value_bool_t;
+    typedef struct const_value_real64_s {const_status_t status;  real64_t  value;  const_value_real64_s (): status(cs_undefined), value(0.0)   {} } const_value_real64_t;
+    typedef struct const_value_int64_s  {const_status_t status;   int64_t  value;  const_value_int64_s  (): status(cs_undefined), value(0)     {} } const_value_int64_t;
+    typedef struct const_value_uint64_s {const_status_t status;  uint64_t  value;  const_value_uint64_s (): status(cs_undefined), value(0)     {} } const_value_uint64_t;
+    typedef struct const_value_bool_s   {const_status_t status;      bool  value;  const_value_bool_s   (): status(cs_undefined), value(false) {} } const_value_bool_t;
 
     typedef struct {
       const_value_real64_t _real64; /* status is initialised to UNDEFINED */
--- a/absyntax_utils/debug_ast.cc	Sun Dec 02 18:20:02 2012 +0100
+++ b/absyntax_utils/debug_ast.cc	Thu Dec 27 15:04:58 2012 +0000
@@ -190,7 +190,7 @@
 
 
 void print_ast_c::print(const char *str) {
-  fprintf(stderr, str);
+  fprintf(stderr, "%s", str);
 }
 
   
@@ -209,7 +209,7 @@
 
 
 void debug_c::print(const char *str) {
-  fprintf(stderr, str);
+  fprintf(stderr, "%s", str);
 }
 
 void debug_c::print(symbol_c *symbol) {
--- a/absyntax_utils/type_initial_value.cc	Sun Dec 02 18:20:02 2012 +0100
+++ b/absyntax_utils/type_initial_value.cc	Thu Dec 27 15:04:58 2012 +0000
@@ -81,7 +81,7 @@
    * for the DATE data type. Untill we fix our implementation, we use 1970-01-01
    * as our default value!!
    */
-    date_literal_0 =  new date_literal_c(integer_1, integer_1, integer_1);
+//date_literal_0 =  new date_literal_c(integer_1, integer_1, integer_1);
   date_literal_0 =  new date_literal_c(new integer_c("1970"), integer_1, integer_1);
   daytime_literal_0 = new daytime_c(integer_0, integer_0, real_0);
   time_0 = new duration_c(new time_type_name_c(), NULL, new interval_c(NULL, NULL, NULL, integer_0, NULL));  // T#0s
@@ -98,9 +98,9 @@
 
 
 
-symbol_c *type_initial_value_c::get(identifier_c *type_name) {
+symbol_c *type_initial_value_c::get(symbol_c *type) {
   TRACE("type_initial_value_c::get(): called ");
-  return (symbol_c *)type_name->accept(*this);
+  return (symbol_c *)type->accept(*type_initial_value_c::instance());
 }
 
 
--- a/absyntax_utils/type_initial_value.hh	Sun Dec 02 18:20:02 2012 +0100
+++ b/absyntax_utils/type_initial_value.hh	Thu Dec 27 15:04:58 2012 +0000
@@ -59,8 +59,10 @@
 
 class type_initial_value_c : public null_visitor_c {
 
+  public:
+    static symbol_c *get(symbol_c *type);
+
   private:
-    static type_initial_value_c *_instance;
     /* constants for the default values of elementary data types... */
     static real_c		*real_0;
     static integer_c		*integer_0, *integer_1;
@@ -74,17 +76,12 @@
     static single_byte_character_string_c *string_0;
     static double_byte_character_string_c *wstring_0;
 
-  public:
-    static type_initial_value_c *instance(void);
-
   protected:
     type_initial_value_c(void);
 
-  public:
-    symbol_c *get(identifier_c *type_name);
-
-
   private:
+    static type_initial_value_c *_instance;
+    static type_initial_value_c *instance(void);
     void *handle_type_spec(symbol_c *base_type_name, symbol_c *type_spec_init);
 
   private:
--- a/main.hh	Sun Dec 02 18:20:02 2012 +0100
+++ b/main.hh	Thu Dec 27 15:04:58 2012 +0000
@@ -48,8 +48,9 @@
 
 
  /* Get the definition of INT16_MAX, INT16_MIN, UINT64_MAX, INT64_MAX, INT64_MIN, ... */
-
+#ifndef __STDC_LIMIT_MACROS
 #define __STDC_LIMIT_MACROS /* required to have UINTxx_MAX defined when including stdint.h from C++ source code. */
+#endif
 #include <stdint.h>         
 #include <limits>
 
@@ -124,7 +125,9 @@
  * e.g. uint64_t v; printf("value=%"PRIu64" !!\n", v);
  * e.g. uint64_t v; printf("value=%"PRIx64" !!\n", v);  // hexadecimal format
  */
+#ifndef __STDC_FORMAT_MACROS
 #define __STDC_FORMAT_MACROS
+#endif
 #include <inttypes.h>
 
 
--- a/stage1_2/iec_bison.yy	Sun Dec 02 18:20:02 2012 +0100
+++ b/stage1_2/iec_bison.yy	Thu Dec 27 15:04:58 2012 +0000
@@ -8265,8 +8265,9 @@
     fprintf (stderr, "Out of memory. Bailing out!\n");
     return -1;
   }
-
-  if(parse_file(libfilename) < 0) {
+  
+  FILE *libfile = NULL;
+  if((libfile = parse_file(libfilename)) == NULL) {
     char *errmsg = strdup2("Error opening library file ", libfilename);
     perror(errmsg);
     free(errmsg);
@@ -8279,7 +8280,8 @@
   full_token_loc = full_token_loc_;
   if (yyparse() != 0)
       ERROR;
-
+  fclose(libfile);
+      
   if (yynerrs > 0) {
     fprintf (stderr, "\n%d error(s) found in %s. Bailing out!\n", yynerrs /* global variable */, libfilename);
     ERROR;
@@ -8299,8 +8301,8 @@
   #if YYDEBUG
     yydebug = 1;
   #endif
-
-  if(parse_file(filename) < 0) {
+  FILE *mainfile = NULL;
+  if ((mainfile = parse_file(filename)) == NULL) {
     char *errmsg = strdup2("Error opening main file ", filename);
     perror(errmsg);
     free(errmsg);
@@ -8315,7 +8317,8 @@
     fprintf (stderr, "\nParsing failed because of too many consecutive syntax errors. Bailing out!\n");
     exit(EXIT_FAILURE);
   }
-
+  fclose(mainfile);
+  
   if (yynerrs > 0) {
     fprintf (stderr, "\n%d error(s) found. Bailing out!\n", yynerrs /* global variable */);
     exit(EXIT_FAILURE);
--- a/stage1_2/iec_flex.ll	Sun Dec 02 18:20:02 2012 +0100
+++ b/stage1_2/iec_flex.ll	Thu Dec 27 15:04:58 2012 +0000
@@ -884,17 +884,28 @@
 			}
 
 
-<<EOF>>			{     /* NOTE: We must not change the value of include_stack_ptr
-			       *       just yet. We must only decrement it if we are NOT
-			       *       at the end of the main file.
-			       *       If we have finished parsing the main file, then we
-			       *       must leave include_stack_ptr at 0, in case the 
-			       *       parser is called once again with a new file.
-			       *       (In fact, we currently do just that!)
+<<EOF>>			{     /* NOTE: Currently bison is incorrectly using END_OF_INPUT in many rules
+			       *       when checking for syntax errors in the input source code.
+			       *       This means that in reality flex will be asked to carry on reading the input
+			       *       even after it has reached the end of all (including the main) input files.
+			       *       In other owrds, we will be called to return more tokens, even after we have
+			       *       already returned an END_OF_INPUT token. In this case, we must carry on returning
+			       *       more END_OF_INPUT tokens.
+			       * 
+			       *       However, in the above case we will be asked to carry on reading more tokens 
+			       *       from the main input file, after we have reached the end. For this to work
+			       *       correctly, we cannot close the main input file!
+			       * 
+			       *       This is why we WILL be called with include_stack_ptr == 0 multiple times,
+			       *       and why we must handle it as a special case
+			       *       that leaves the include_stack_ptr unchanged, and returns END_OF_INPUT once again.
+			       * 
+			       *       As a corollory, flex can never safely close the main input file, and we must ask
+			       *       bison to close it!
 			       */
-			  fclose(yyin);
-			  free(current_tracking);
 			  if (include_stack_ptr == 0) {
+			      // fclose(yyin);           // Must not do this!!
+			      // free(current_tracking); // Must not do this!!
 			      /* yyterminate() terminates the scanner and returns a 0 to the 
 			       * scanner's  caller, indicating "all done".
 			       *	
@@ -905,6 +916,8 @@
 			       */ 	
 			    yyterminate();
 			  } else {
+			    fclose(yyin);
+			    free(current_tracking);
 			    --include_stack_ptr;
 			    yy_delete_buffer(YY_CURRENT_BUFFER);
 			    yy_switch_to_buffer((include_stack[include_stack_ptr]).buffer_state);
@@ -1864,18 +1877,18 @@
 /* Tell flex which file to parse. This function will not imediately start parsing the file.
  * To parse the file, you then need to call yyparse()
  *
- * Returns -1 on error opening the file (and a valid errno), or 0 on success.
- */
-int parse_file(const char *filename) {
+ * Returns NULL on error opening the file (and a valid errno), or 0 on success.
+ * Caller must close the file!
+ */
+FILE *parse_file(const char *filename) {
   FILE *filehandle = NULL;
 
-  if((filehandle = fopen(filename, "r")) == NULL) 
-    return -1;
-
-  yyin = filehandle;
-  current_filename = strdup(filename);
-  current_tracking = GetNewTracking(yyin);
-  return 0;
+  if((filehandle = fopen(filename, "r")) != NULL) {
+    yyin = filehandle;
+    current_filename = strdup(filename);
+    current_tracking = GetNewTracking(yyin);
+  }
+  return filehandle;
 }
 
 
--- a/stage1_2/stage1_2_priv.hh	Sun Dec 02 18:20:02 2012 +0100
+++ b/stage1_2/stage1_2_priv.hh	Thu Dec 27 15:04:58 2012 +0000
@@ -126,10 +126,10 @@
 /* Tell flex which file to parse. This function will not imediately start parsing the file.
  * To parse the file, you then need to call yyparse()
  *
- * Returns -1 on error opening the file (and a valid errno), or 0 on success.
- */
-int parse_file(const char *filename);
-
+ * Returns NULL on error opening the file (and a valid errno), or 0 on success.
+ * Caller must close the file!
+ */
+FILE *parse_file(const char *filename);
 
 
 
--- a/stage3/constant_folding.cc	Sun Dec 02 18:20:02 2012 +0100
+++ b/stage3/constant_folding.cc	Thu Dec 27 15:04:58 2012 +0000
@@ -206,8 +206,27 @@
 		{SET_NONCONST(dtype, symbol);}                                                                            \
 }
 
-
-
+/* Constant Propagation: Rules for Meet from "Cooper K., Torczon L. - Engineering a Compiler, Second Edition - 2011"
+ * at 9.3 Static Single-Assignment Form  page 517
+ * - any * undefined = any
+ * - any * non_const = non_const
+ * - constant * constant = constant  (if equal)
+ * - constant * constant = non_const (if not equal)
+ */
+#define COMPUTE_MEET_SEMILATTICE(dtype, c1, c2, resValue) {\
+		if (( c1._##dtype.value  != c2._##dtype.value && c2._##dtype.status == symbol_c::cs_const_value &&\
+              c1._##dtype.status == symbol_c::cs_const_value) ||\
+		    ( c1._##dtype.status == symbol_c::cs_non_const && c2._##dtype.status == symbol_c::cs_const_value ) ||\
+		    ( c2._##dtype.status == symbol_c::cs_non_const && c1._##dtype.status == symbol_c::cs_const_value  )) {\
+			resValue._##dtype.status = symbol_c::cs_non_const;\
+		} else {\
+			resValue._##dtype.status = symbol_c::cs_const_value;\
+			resValue._##dtype.value  = c1._##dtype.value;\
+		}\
+}
+
+
+static std::map <std::string, symbol_c::const_value_t> values;
 
 
 /***********************************************************************/
@@ -916,6 +935,37 @@
 	return NULL;
 }
 
+/*********************/
+/* B 1.4 - Variables */
+/*********************/
+void *constant_folding_c::visit(symbolic_variable_c *symbol) {
+	std::string varName;
+
+	varName = convert.toString(symbol->var_name);
+	if (values.count(varName) > 0) {
+		symbol->const_value = values[varName];
+	}
+	return NULL;
+}
+
+/**********************/
+/* B 1.5.3 - Programs */
+/**********************/
+void *constant_folding_c::visit(program_declaration_c *symbol) {
+	symbol_c *var_name;
+
+	values.clear(); /* Clear global map */
+	search_var_instance_decl_c search_var_instance_decl(symbol);
+	function_param_iterator_c fpi(symbol);
+	while((var_name = fpi.next()) != NULL) {
+		std::string varName = convert.toString(var_name);
+		symbol_c   *varDecl = search_var_instance_decl.get_decl(var_name);
+		values[varName] = varDecl->const_value;
+	}
+	/* Add all variables declared into Values map and put them to initial value */
+	symbol->function_block_body->accept(*this);
+	return NULL;
+}
 
 
 /****************************************/
@@ -1185,3 +1235,60 @@
 
 /* TODO: handle function invocations... */
 // void *fill_candidate_datatypes_c::visit(function_invocation_c *symbol) {}
+
+
+
+
+/*********************************/
+/* B 3.2.1 Assignment Statements */
+/*********************************/
+void *constant_folding_c::visit(assignment_statement_c *symbol) {
+	std::string varName;
+
+	symbol->r_exp->accept(*this);
+	symbol->l_exp->const_value = symbol->r_exp->const_value;
+	varName = convert.toString(symbol->l_exp);
+	values[varName] = symbol->l_exp->const_value;
+	return NULL;
+}
+
+/********************************/
+/* B 3.2.3 Selection Statements */
+/********************************/
+void *constant_folding_c::visit(if_statement_c *symbol) {
+	std::map <std::string, symbol_c::const_value_t> values_incoming;
+	std::map <std::string, symbol_c::const_value_t> values_statement_result;
+	std::map <std::string, symbol_c::const_value_t> values_elsestatement_result;
+	std::map <std::string, symbol_c::const_value_t>::iterator itr;
+	values_incoming = values; /* save incoming status */
+
+	symbol->statement_list->accept(*this);
+	values_statement_result = values;
+	if (NULL != symbol->else_statement_list) {
+		values = values_incoming;
+		symbol->else_statement_list->accept(*this);
+		values_elsestatement_result = values;
+	} else
+		values_elsestatement_result = values_incoming;
+	values.clear();
+	itr = values_statement_result.begin();
+	for ( ; itr != values_statement_result.end(); ++itr) {
+		std::string name = itr->first;
+		symbol_c::const_value_t value;
+
+		if (values_elsestatement_result.count(name) > 0) {
+			symbol_c::const_value_t c1 = itr->second;
+			symbol_c::const_value_t c2 = values_elsestatement_result[name];
+			COMPUTE_MEET_SEMILATTICE (real64, c1, c2, value);
+			COMPUTE_MEET_SEMILATTICE (uint64, c1, c2, value);
+			COMPUTE_MEET_SEMILATTICE ( int64, c1, c2, value);
+			COMPUTE_MEET_SEMILATTICE (  bool, c1, c2, value);
+		} else
+			value = values_statement_result[name];
+		values[name] = value;
+	}
+	return NULL;
+}
+
+
+
--- a/stage3/constant_folding.hh	Sun Dec 02 18:20:02 2012 +0100
+++ b/stage3/constant_folding.hh	Thu Dec 27 15:04:58 2012 +0000
@@ -43,9 +43,31 @@
 #include "../absyntax_utils/absyntax_utils.hh"
 
 
+class convert_c : public iterator_visitor_c {
+	std::string text;
+
+public:
+	convert_c(symbol_c *symbol = NULL) {
+		text = "";
+	}
+
+	std::string toString(symbol_c *symbol) {
+		symbol->accept(*this);
+		return text;
+	}
+
+	void *visit(identifier_c *symbol) {
+		text = symbol->value;
+		return NULL;
+	}
+
+	void *visit(symbolic_variable_c *symbol) {
+		symbol->var_name->accept(*this);
+		return NULL;
+	}
+};
 
 class constant_folding_c : public iterator_visitor_c {
-  private:
     search_varfb_instance_type_c *search_varfb_instance_type;
     int error_count;
     bool warning_found;
@@ -54,6 +76,7 @@
     symbol_c *prev_il_instruction;
     /* the current IL operand being analyzed */
     symbol_c *il_operand;
+    convert_c convert;
 
   public:
 	constant_folding_c(symbol_c *symbol = NULL);
@@ -86,6 +109,16 @@
     /********* **************/
     void *visit(fixed_point_c *symbol);
 
+    /*********************/
+    /* B 1.4 - Variables */
+    /*********************/
+    void *visit(symbolic_variable_c *symbol);
+
+    /**********************/
+    /* B 1.5.3 - Programs */
+    /**********************/
+    void *visit(program_declaration_c *symbol);
+
     /****************************************/
     /* B.2 - Language IL (Instruction List) */
     /****************************************/
@@ -178,6 +211,16 @@
     void *visit(   neg_expression_c *symbol);
     void *visit(   not_expression_c *symbol);
     //void *visit(function_invocation_c *symbol); /* TODO */
+
     
+    /*********************************/
+    /* B 3.2.1 Assignment Statements */
+    /*********************************/
+    void *visit(assignment_statement_c *symbol);
+
+    /********************************/
+    /* B 3.2.3 Selection Statements */
+    /********************************/
+    void *visit(if_statement_c *symbol);
 };
 
--- a/stage4/generate_c/generate_c.cc	Sun Dec 02 18:20:02 2012 +0100
+++ b/stage4/generate_c/generate_c.cc	Thu Dec 27 15:04:58 2012 +0000
@@ -1124,7 +1124,7 @@
   s4o.print(" = ");
   {
     /* get the default value of this variable's type */
-    symbol_c *default_value = (symbol_c *)symbol->type_name->accept(*type_initial_value_c::instance());
+    symbol_c *default_value = type_initial_value_c::get(symbol->type_name);
     if (default_value == NULL) ERROR;
     initialization_analyzer_c initialization_analyzer(default_value);
     switch (initialization_analyzer.get_initialization_type()) {
--- a/stage4/generate_c/generate_c_il.cc	Sun Dec 02 18:20:02 2012 +0100
+++ b/stage4/generate_c/generate_c_il.cc	Thu Dec 27 15:04:58 2012 +0000
@@ -903,7 +903,7 @@
           s4o.print(",\n"+s4o.indent_spaces);
         if (param_value == NULL) {
           /* If not, get the default value of this variable's type */
-          param_value = (symbol_c *)current_param_type->accept(*type_initial_value_c::instance());
+          param_value = type_initial_value_c::get(current_param_type);
         }
         if (param_value == NULL) ERROR;
         s4o.print("(");
@@ -1292,7 +1292,7 @@
           s4o.print(",\n"+s4o.indent_spaces);
         if (param_value == NULL) {
           /* If not, get the default value of this variable's type */
-          param_value = (symbol_c *)current_param_type->accept(*type_initial_value_c::instance());
+          param_value = type_initial_value_c::get(current_param_type);
         }
         if (param_value == NULL) ERROR;
         s4o.print("(");
--- a/stage4/generate_c/generate_c_st.cc	Sun Dec 02 18:20:02 2012 +0100
+++ b/stage4/generate_c/generate_c_st.cc	Thu Dec 27 15:04:58 2012 +0000
@@ -752,7 +752,7 @@
           s4o.print(",\n"+s4o.indent_spaces);
         if (param_value == NULL) {
           /* If not, get the default value of this variable's type */
-          param_value = (symbol_c *)current_param_type->accept(*type_initial_value_c::instance());
+          param_value = type_initial_value_c::get(current_param_type);
         }
         if (param_value == NULL) ERROR;
         s4o.print("(");
--- a/stage4/generate_c/generate_c_vardecl.cc	Sun Dec 02 18:20:02 2012 +0100
+++ b/stage4/generate_c/generate_c_vardecl.cc	Thu Dec 27 15:04:58 2012 +0000
@@ -195,7 +195,7 @@
         case arraysize_am:
           symbol->array_subrange_list->accept(*this);
           array_base_type = symbol->non_generic_type_name;
-          array_default_value = (symbol_c *)symbol->non_generic_type_name->accept(*type_initial_value_c::instance());;
+          array_default_value = type_initial_value_c::get(symbol->non_generic_type_name);
           if (array_default_value == NULL) ERROR;
           break;
         case typedecl_am:
@@ -618,7 +618,7 @@
           if (current_element_type == NULL) ERROR;
           
           /* If not, get the default value of this variable's type */
-          element_value = (symbol_c *)current_element_type->accept(*type_initial_value_c::instance());
+          element_value = type_initial_value_c::get(current_element_type);
         }
         
         if (element_value == NULL) ERROR;
@@ -878,7 +878,7 @@
         ERROR;
       if (NULL == this->current_var_init_symbol) {
         /* We try to find the data type's default value... */
-        this->current_var_init_symbol = (symbol_c *)this->current_var_type_symbol->accept(*type_initial_value_c::instance());
+        this->current_var_init_symbol = type_initial_value_c::get(this->current_var_type_symbol);
       /* Note that Function Block 'data types' do not have a default value, so we cannot abort if no default value is found! */
       /*
       if (NULL == this->current_var_init_symbol)