# HG changeset patch # User Mario de Sousa # Date 1330343043 0 # Node ID 67d8b07bac223139ce56aff9d57d281cb9824ffc # Parent ca8d98289ff922cde5ff9d214ea01908238fda28 Change prev_il_instruction to a vector<> diff -r ca8d98289ff9 -r 67d8b07bac22 absyntax/absyntax.def --- a/absyntax/absyntax.def Mon Feb 27 11:28:51 2012 +0000 +++ b/absyntax/absyntax.def Mon Feb 27 11:44:03 2012 +0000 @@ -917,7 +917,7 @@ * In case of an il instruction preceded by a label, this will include all IL instructions that jump to this label! * It is filled in by the flow_control_analysis_c during stage 3. */ -SYM_REF2(il_instruction_c, label, il_instruction, symbol_c *prev_il_instruction;) +SYM_REF2(il_instruction_c, label, il_instruction, std::vector prev_il_instruction;) /* | il_simple_operator [il_operand] */ @@ -965,7 +965,7 @@ * | il_formal_funct_call eol_list */ /* NOTE: The parameter 'prev_il_instruction' is used to point to all previous il instructions that may be executed imedaitely before this instruction. */ -SYM_REF1(il_simple_instruction_c, il_simple_instruction, symbol_c *prev_il_instruction;) +SYM_REF1(il_simple_instruction_c, il_simple_instruction, std::vector prev_il_instruction;) /* | il_initial_param_list il_param_instruction */ SYM_LIST(il_param_list_c) diff -r ca8d98289ff9 -r 67d8b07bac22 readme --- a/readme Mon Feb 27 11:28:51 2012 +0000 +++ b/readme Mon Feb 27 11:44:03 2012 +0000 @@ -145,13 +145,15 @@ Pass 1: Analyses the possible data types each expression/literal/IL instruction/etc. may take Implemented in -> stage3/fill_candidate_datatypes_c This will anotate the abstract syntax tree - (Every object of in the abstract syntax tree that may have a data type, will have the variable 'candidate_datatypes' correctly filled in.) - Pass 2: Narrows all the possible data types each expression/literal/IL instruction/etc. may take down to a single data type + (Every object of in the abstract syntax tree that may have a data type, will have the variable 'candidate_datatypes' correctly filled in. + Additionally, objects in the abstract syntax tree that represen function invocations will have the variable + 'candidate_functions' correctly filled in.) +Pass 2: Narrows all the possible data types each expression/literal/IL instruction/etc. may take down to a single data type Implemented in -> stage3/narrow_candidate_datatypes_c This will anotate the abstract syntax tree (Every object of in the abstract syntax tree that may have a data type, will have the variable 'datatype' correctly filled in. Additionally, objects in the abstract syntax tree that represen function invocations will have the variables - 'called_function_declaration', 'extensible_param_count' and 'candidate_functions' correctly filled in. + 'called_function_declaration' and 'extensible_param_count' correctly filled in. Additionally, objects in the abstract syntax tree that represen function block (FB) invocations will have the variable 'called_fb_declaration' correctly filled in.) Pass 2: Prints error messages in the event of the IEC 61131-3 source code being analysed contains semantic data type incompatibility errors. diff -r ca8d98289ff9 -r 67d8b07bac22 stage3/datatype_functions.cc --- a/stage3/datatype_functions.cc Mon Feb 27 11:28:51 2012 +0000 +++ b/stage3/datatype_functions.cc Mon Feb 27 11:44:03 2012 +0000 @@ -24,7 +24,8 @@ #include "datatype_functions.hh" #include "../absyntax_utils/absyntax_utils.hh" -#include +#include +// #include @@ -71,14 +72,14 @@ const struct widen_entry widen_SUB_table[] = { - { &search_constant_type_c::time_type_name, &search_constant_type_c::time_type_name, &search_constant_type_c::time_type_name }, - { &search_constant_type_c::tod_type_name, &search_constant_type_c::tod_type_name, &search_constant_type_c::tod_type_name }, - { &search_constant_type_c::dt_type_name, &search_constant_type_c::dt_type_name, &search_constant_type_c::dt_type_name }, - { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safetime_type_name, &search_constant_type_c::safetime_type_name }, - { &search_constant_type_c::safetod_type_name, &search_constant_type_c::safetod_type_name, &search_constant_type_c::safetod_type_name }, - { &search_constant_type_c::safedt_type_name, &search_constant_type_c::safedt_type_name, &search_constant_type_c::safedt_type_name }, - - { &search_constant_type_c::tod_type_name, &search_constant_type_c::time_type_name, &search_constant_type_c::tod_type_name }, + { &search_constant_type_c::time_type_name, &search_constant_type_c::time_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::tod_type_name, &search_constant_type_c::tod_type_name, &search_constant_type_c::tod_type_name }, + { &search_constant_type_c::dt_type_name, &search_constant_type_c::dt_type_name, &search_constant_type_c::dt_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safetime_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetod_type_name, &search_constant_type_c::safetod_type_name, &search_constant_type_c::safetod_type_name }, + { &search_constant_type_c::safedt_type_name, &search_constant_type_c::safedt_type_name, &search_constant_type_c::safedt_type_name }, + + { &search_constant_type_c::tod_type_name, &search_constant_type_c::time_type_name, &search_constant_type_c::tod_type_name }, { &search_constant_type_c::safetod_type_name, &search_constant_type_c::time_type_name, &search_constant_type_c::tod_type_name }, { &search_constant_type_c::tod_type_name, &search_constant_type_c::safetime_type_name, &search_constant_type_c::tod_type_name }, { &search_constant_type_c::safetod_type_name, &search_constant_type_c::safetime_type_name, &search_constant_type_c::safetod_type_name }, @@ -136,7 +137,7 @@ }; const struct widen_entry widen_DIV_table[] = { - { &search_constant_type_c::time_type_name, &search_constant_type_c::lreal_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::time_type_name, &search_constant_type_c::lreal_type_name, &search_constant_type_c::time_type_name }, { &search_constant_type_c::time_type_name, &search_constant_type_c::real_type_name, &search_constant_type_c::time_type_name }, { &search_constant_type_c::time_type_name, &search_constant_type_c::dint_type_name, &search_constant_type_c::time_type_name }, { &search_constant_type_c::time_type_name, &search_constant_type_c::int_type_name, &search_constant_type_c::time_type_name }, @@ -201,6 +202,27 @@ +/* Intersect two candidate_datatype_lists. + * Remove from list1 (origin, dest.) all elements that are not found in list2 (with). + * In essence, list1 will contain the result of the intersection of list1 with list2. + * In other words, modify list1 so it only contains the elelements that are simultaneously in list1 and list2! + */ +void intersect_candidate_datatype_list(symbol_c *list1 /*origin, dest.*/, symbol_c *list2 /*with*/) { + if ((NULL == list1) || (NULL == list2)) + /* In principle, we should never call it with NULL values. Best to abort the compiler just in case! */ + return; + + for(std::vector::iterator i = list1->candidate_datatypes.begin(); i < list1->candidate_datatypes.end(); ) { + /* Note that we do _not_ increment i in the for() loop! + * When we erase an element from position i, a new element will take it's place, that must also be tested! + */ + if (search_in_candidate_datatype_list(*i, list2->candidate_datatypes) < 0) + /* remove this element! This will change the value of candidate_datatypes.size() */ + list1->candidate_datatypes.erase(i); + else i++; + } +} + /* A helper function... */ diff -r ca8d98289ff9 -r 67d8b07bac22 stage3/datatype_functions.hh --- a/stage3/datatype_functions.hh Mon Feb 27 11:28:51 2012 +0000 +++ b/stage3/datatype_functions.hh Mon Feb 27 11:44:03 2012 +0000 @@ -146,6 +146,13 @@ */ void copy_candidate_datatype_list(symbol_c *from, symbol_c *to); +/* Intersect two candidate_datatype_lists. + * Remove from list1 (origin, dest.) all elements that are not found in list2 (with). + * In essence, list1 will contain the result of the intersection of list1 with list2. + * In other words, modify list1 so it only contains the elelements that are simultaneously in list1 and list2! + */ +void intersect_candidate_datatype_list(symbol_c *list1 /*origin, dest.*/, symbol_c *list2 /*with*/); + /* A helper function... */ bool is_ANY_ELEMENTARY_type (symbol_c *type_symbol); diff -r ca8d98289ff9 -r 67d8b07bac22 stage3/fill_candidate_datatypes.cc --- a/stage3/fill_candidate_datatypes.cc Mon Feb 27 11:28:51 2012 +0000 +++ b/stage3/fill_candidate_datatypes.cc Mon Feb 27 11:44:03 2012 +0000 @@ -808,10 +808,16 @@ /* This empty/null il_instruction does not change the value of the current/default IL variable. * So it inherits the candidate_datatypes from it's previous IL instructions! */ - if (NULL != symbol->prev_il_instruction) - copy_candidate_datatype_list(symbol->prev_il_instruction /*from*/, symbol /*to*/); + if (!symbol->prev_il_instruction.empty()) { + copy_candidate_datatype_list(symbol->prev_il_instruction[0] /*from*/, symbol /*to*/); + for (unsigned int i = 1; i < symbol->prev_il_instruction.size(); i++) { + intersect_candidate_datatype_list(symbol /*origin, dest.*/, symbol->prev_il_instruction[i] /*with*/); + } + } } else { - prev_il_instruction = symbol->prev_il_instruction; + if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */ + if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL; + else prev_il_instruction = symbol->prev_il_instruction[0]; symbol->il_instruction->accept(*this); prev_il_instruction = NULL; @@ -1011,9 +1017,14 @@ return NULL; } + + + // SYM_REF1(il_simple_instruction_c, il_simple_instruction, symbol_c *prev_il_instruction;) void *fill_candidate_datatypes_c::visit(il_simple_instruction_c *symbol) { - prev_il_instruction = symbol->prev_il_instruction; + if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */ + if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL; + else prev_il_instruction = symbol->prev_il_instruction[0]; symbol->il_simple_instruction->accept(*this); prev_il_instruction = NULL; diff -r ca8d98289ff9 -r 67d8b07bac22 stage3/flow_control_analysis.cc --- a/stage3/flow_control_analysis.cc Mon Feb 27 11:28:51 2012 +0000 +++ b/stage3/flow_control_analysis.cc Mon Feb 27 11:44:03 2012 +0000 @@ -190,7 +190,7 @@ // SYM_REF2(il_instruction_c, label, il_instruction) // void *visit(instruction_list_c *symbol); void *flow_control_analysis_c::visit(il_instruction_c *symbol) { - symbol->prev_il_instruction = prev_il_instruction; + symbol->prev_il_instruction.push_back(prev_il_instruction); /* TODO: handle labels correctly! * * Don't forget to handle multiple consecutive lables too! @@ -268,7 +268,7 @@ // SYM_REF1(il_simple_instruction_c, il_simple_instruction, symbol_c *prev_il_instruction;) void *flow_control_analysis_c::visit(il_simple_instruction_c*symbol) { - symbol->prev_il_instruction = prev_il_instruction; + symbol->prev_il_instruction.push_back(prev_il_instruction); return NULL; } diff -r ca8d98289ff9 -r 67d8b07bac22 stage3/narrow_candidate_datatypes.cc --- a/stage3/narrow_candidate_datatypes.cc Mon Feb 27 11:28:51 2012 +0000 +++ b/stage3/narrow_candidate_datatypes.cc Mon Feb 27 11:44:03 2012 +0000 @@ -64,6 +64,13 @@ +/* Only set the symbol's desired datatype to 'datatype' if that datatype is in the candidate_datatype list */ +static void set_datatype_in_prev_il_instruction(symbol_c *datatype, il_instruction_c *symbol) { + for (unsigned int i = 0; i < symbol->prev_il_instruction.size(); i++) + set_datatype(datatype, symbol->prev_il_instruction[i]); +} + + bool narrow_candidate_datatypes_c::is_widening_compatible(symbol_c *left_type, symbol_c *right_type, symbol_c *result_type, const struct widen_entry widen_table[]) { for (int k = 0; NULL != widen_table[k].left; k++) { @@ -503,12 +510,12 @@ void *narrow_candidate_datatypes_c::visit(il_instruction_c *symbol) { if (NULL == symbol->il_instruction) { /* this empty/null il_instruction cannot generate the desired datatype. We pass on the request to the previous il instruction. */ - if (NULL != symbol->prev_il_instruction) - symbol->prev_il_instruction->datatype = symbol->datatype; + set_datatype_in_prev_il_instruction(symbol->datatype, symbol); } else { /* Tell the il_instruction the datatype that it must generate - this was chosen by the next il_instruction (remember: we are iterating backwards!) */ - symbol->il_instruction->datatype = symbol->datatype; - prev_il_instruction = symbol->prev_il_instruction; + if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */ + if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL; + else prev_il_instruction = symbol->prev_il_instruction[0]; symbol->il_instruction->accept(*this); prev_il_instruction = NULL; } @@ -657,7 +664,9 @@ // SYM_REF1(il_simple_instruction_c, il_simple_instruction, symbol_c *prev_il_instruction;) void *narrow_candidate_datatypes_c::visit(il_simple_instruction_c *symbol) { - prev_il_instruction = symbol->prev_il_instruction; + if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */ + if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL; + else prev_il_instruction = symbol->prev_il_instruction[0]; symbol->il_simple_instruction->datatype = symbol->datatype; symbol->il_simple_instruction->accept(*this); prev_il_instruction = NULL; diff -r ca8d98289ff9 -r 67d8b07bac22 stage3/print_datatypes_error.cc --- a/stage3/print_datatypes_error.cc Mon Feb 27 11:28:51 2012 +0000 +++ b/stage3/print_datatypes_error.cc Mon Feb 27 11:44:03 2012 +0000 @@ -598,7 +598,10 @@ // SYM_REF2(il_instruction_c, label, il_instruction) void *print_datatypes_error_c::visit(il_instruction_c *symbol) { if (NULL != symbol->il_instruction) { - prev_il_instruction = symbol->prev_il_instruction; + if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */ + if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL; + else prev_il_instruction = symbol->prev_il_instruction[0]; + symbol->il_instruction->accept(*this); prev_il_instruction = NULL; } @@ -736,7 +739,10 @@ // SYM_REF1(il_simple_instruction_c, il_simple_instruction, symbol_c *prev_il_instruction;) void *print_datatypes_error_c::visit(il_simple_instruction_c *symbol) { - prev_il_instruction = symbol->prev_il_instruction; + if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */ + if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL; + else prev_il_instruction = symbol->prev_il_instruction[0]; + symbol->il_simple_instruction->accept(*this); prev_il_instruction = NULL; return NULL;