# HG changeset patch # User Mario de Sousa # Date 1356620698 0 # Node ID e74a882c8d2226347916a6b0201e6f274c89346a # Parent 96a1199d073974a861f7c8349f1f2d9dc484c0f7# Parent 30e5193cc19ab99601de3b0690163e51cccf6c0d merge diff -r 30e5193cc19a -r e74a882c8d22 absyntax/absyntax.hh --- 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 */ diff -r 30e5193cc19a -r e74a882c8d22 absyntax_utils/debug_ast.cc --- 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) { diff -r 30e5193cc19a -r e74a882c8d22 absyntax_utils/type_initial_value.cc --- 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()); } diff -r 30e5193cc19a -r e74a882c8d22 absyntax_utils/type_initial_value.hh --- 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: diff -r 30e5193cc19a -r e74a882c8d22 main.hh --- 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 #include @@ -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 diff -r 30e5193cc19a -r e74a882c8d22 stage1_2/iec_bison.yy --- 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); diff -r 30e5193cc19a -r e74a882c8d22 stage1_2/iec_flex.ll --- 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 @@ } -<> { /* 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!) +<> { /* 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; } diff -r 30e5193cc19a -r e74a882c8d22 stage1_2/stage1_2_priv.hh --- 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); diff -r 30e5193cc19a -r e74a882c8d22 stage3/constant_folding.cc --- 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 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 values_incoming; + std::map values_statement_result; + std::map values_elsestatement_result; + std::map ::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; +} + + + diff -r 30e5193cc19a -r e74a882c8d22 stage3/constant_folding.hh --- 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); }; diff -r 30e5193cc19a -r e74a882c8d22 stage4/generate_c/generate_c.cc --- 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()) { diff -r 30e5193cc19a -r e74a882c8d22 stage4/generate_c/generate_c_il.cc --- 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("("); diff -r 30e5193cc19a -r e74a882c8d22 stage4/generate_c/generate_c_st.cc --- 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("("); diff -r 30e5193cc19a -r e74a882c8d22 stage4/generate_c/generate_c_vardecl.cc --- 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)