# HG changeset patch # User mjsousa # Date 1376993740 -3600 # Node ID 783ef40344dd9ad69f9d22dbc4bad8c5e95512b5 # Parent 27f246b35ac2c5f573bd4393dbcd92ca79156412 Add support for FB call semantics of 'S' and 'R' IL operators! Remove segfaults when analysing buggy IL code (IL operators with no operands). diff -r 27f246b35ac2 -r 783ef40344dd stage3/fill_candidate_datatypes.cc --- a/stage3/fill_candidate_datatypes.cc Tue Aug 20 11:11:09 2013 +0100 +++ b/stage3/fill_candidate_datatypes.cc Tue Aug 20 11:15:40 2013 +0100 @@ -555,17 +555,13 @@ * CU counter_var */ void *fill_candidate_datatypes_c::handle_implicit_il_fb_call(symbol_c *il_instruction, const char *param_name, symbol_c *&called_fb_declaration) { - symbol_c *fb_type_id = search_varfb_instance_type->get_basetype_id(il_operand); - /* Although a call to a non-declared FB is a semantic error, this is currently caught by stage 2! */ - if (NULL == fb_type_id) ERROR; - - function_block_declaration_c *fb_decl = function_block_type_symtable.find_value(fb_type_id); - if (function_block_type_symtable.end_value() == fb_decl) - /* The il_operand is not the name of a FB instance. Most probably it is the name of a variable of some other type. - * this is a semantic error. - */ - fb_decl = NULL; - + symbol_c *fb_decl = (NULL == il_operand)? NULL : search_varfb_instance_type->get_basetype_decl(il_operand); + if (! get_datatype_info_c::is_function_block(fb_decl)) fb_decl = NULL; + + /* Although a call to a non-declared FB is a semantic error, this is currently caught by stage 2! */ + /* However, when calling using the 'S' and 'R' operators, this error is not caught by stage 2, as these operators have two possible semantics */ + // if (NULL == fb_type_id) ERROR; + /* The narrow_candidate_datatypes_c does not rely on this called_fb_declaration pointer being == NULL to conclude that * we have a datatype incompatibility error, so we set it to fb_decl to allow the print_datatype_error_c to print out * more informative error messages! @@ -594,10 +590,54 @@ + +/* handle the S and R IL operators... */ +/* operator_str should be set to either "S" or "R" */ +void *fill_candidate_datatypes_c::handle_S_and_R_operator(symbol_c *symbol, const char *operator_str, symbol_c *&called_fb_declaration) { + /* NOTE: this operator has two possible semantic meanings: + * - Set/Reset the BOOL operand variable to true + * - call the FB specified by the operand. + * Which of the two semantics will have to be determined by the datatype of the operand! + */ + symbol_c *prev_instruction_type, *operand_type; + + if (NULL == prev_il_instruction) return NULL; + if (NULL == il_operand) return NULL; + + for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { + prev_instruction_type = prev_il_instruction->candidate_datatypes[i]; + operand_type = il_operand->candidate_datatypes[j]; + /* IEC61131-3, Table 52, Note (e) states that the datatype of the operand must be BOOL! + * IEC61131-3, Table 52, line 3 states that this operator should "Set operand to 1 if current result is Boolean 1" + * which implies that the prev_instruction_type MUST also be BOOL compatible. + */ + if (get_datatype_info_c::is_BOOL_compatible(prev_instruction_type) && get_datatype_info_c::is_BOOL_compatible(operand_type)) + add_datatype_to_candidate_list(symbol, prev_instruction_type); + } + } + + /* if the appropriate semantics is not a Set/Reset of a boolean variable, the we try for the FB invocation! */ + if (symbol->candidate_datatypes.size() == 0) + handle_implicit_il_fb_call(symbol, operator_str, called_fb_declaration); + + /* If it is also not a valid FB call, make sure the candidate_datatypes is empty (handle_implicit_il_fb_call may leave it non-empty!!) */ + /* From here on out, all later code will consider the symbol->called_fb_declaration being NULL as an indication that this operator must use the + * Set/Reset semantics, so we must also guarantee that the remainder of the state of this symbol is compatible with that assumption! + */ + if (NULL == called_fb_declaration) + symbol->candidate_datatypes.clear(); + + if (debug) std::cout << operator_str << " [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + return NULL; +} + + + /* handle a binary IL operator, like ADD, SUB, etc... */ void *fill_candidate_datatypes_c::handle_binary_operator(const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr) { - if (NULL == l_expr) /* if no prev_il_instruction */ - return NULL; + if (NULL == l_expr) return NULL; /* if no prev_il_instruction */ + if (NULL == r_expr) return NULL; /* if no IL operand!! */ for(unsigned int i = 0; i < l_expr->candidate_datatypes.size(); i++) for(unsigned int j = 0; j < r_expr->candidate_datatypes.size(); j++) @@ -1553,21 +1593,11 @@ * | il_call_operator prev_declared_fb_name '(' il_operand_list ')' * | il_call_operator prev_declared_fb_name '(' eol_list il_param_list ')' */ -/* NOTE: The parameter 'called_fb_declaration'is used to pass data between stage 3 and stage4 (although currently it is not used in stage 4 */ +/* NOTE: The parameter 'called_fb_declaration'is used to pass data between stage 3 and stage4 */ // SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list, symbol_c *called_fb_declaration) void *fill_candidate_datatypes_c::visit(il_fb_call_c *symbol) { - /* We do not call - * fb_decl = search_varfb_instance_type->get_basetype_decl(symbol->fb_name); - * because we want to make sure it is a FB instance, and not some other data type... - */ - symbol_c *fb_type_id = search_varfb_instance_type->get_basetype_id(symbol->fb_name); - /* Although a call to a non-declared FB is a semantic error, this is currently caught by stage 2! */ - if (NULL == fb_type_id) ERROR; - - function_block_declaration_c *fb_decl = function_block_type_symtable.find_value(fb_type_id); - if (function_block_type_symtable.end_value() == fb_decl) - /* The fb_name not the name of a FB instance. Most probably it is the name of a variable of some other type. */ - fb_decl = NULL; + symbol_c *fb_decl = search_varfb_instance_type->get_basetype_decl(symbol->fb_name); + if (! get_datatype_info_c::is_function_block(fb_decl)) fb_decl = NULL; /* Although a call to a non-declared FB is a semantic error, this is currently caught by stage 2! */ if (NULL == fb_decl) ERROR; @@ -1664,6 +1694,7 @@ /* B 2.2 Operators */ /*******************/ void *fill_candidate_datatypes_c::visit(LD_operator_c *symbol) { + if (NULL == il_operand) return NULL; for(unsigned int i = 0; i < il_operand->candidate_datatypes.size(); i++) { add_datatype_to_candidate_list(symbol, il_operand->candidate_datatypes[i]); } @@ -1672,6 +1703,7 @@ } void *fill_candidate_datatypes_c::visit(LDN_operator_c *symbol) { + if (NULL == il_operand) return NULL; for(unsigned int i = 0; i < il_operand->candidate_datatypes.size(); i++) { if (get_datatype_info_c::is_ANY_BIT_compatible(il_operand->candidate_datatypes[i])) add_datatype_to_candidate_list(symbol, il_operand->candidate_datatypes[i]); @@ -1684,6 +1716,7 @@ symbol_c *prev_instruction_type, *operand_type; if (NULL == prev_il_instruction) return NULL; + if (NULL == il_operand) return NULL; for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { prev_instruction_type = prev_il_instruction->candidate_datatypes[i]; @@ -1700,6 +1733,7 @@ symbol_c *prev_instruction_type, *operand_type; if (NULL == prev_il_instruction) return NULL; + if (NULL == il_operand) return NULL; for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { prev_instruction_type = prev_il_instruction->candidate_datatypes[i]; @@ -1720,6 +1754,7 @@ * We do not need to generate an error message. This error will be caught somewhere else! */ if (NULL == prev_il_instruction) return NULL; + if (NULL == il_operand) return NULL; for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { if (get_datatype_info_c::is_ANY_BIT_compatible(prev_il_instruction->candidate_datatypes[i])) add_datatype_to_candidate_list(symbol, prev_il_instruction->candidate_datatypes[i]); @@ -1729,58 +1764,17 @@ } -void *fill_candidate_datatypes_c::visit(S_operator_c *symbol) { - /* TODO: what if this is a FB call ?? */ - symbol_c *prev_instruction_type, *operand_type; - - if (NULL == prev_il_instruction) return NULL; - for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { - for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { - prev_instruction_type = prev_il_instruction->candidate_datatypes[i]; - operand_type = il_operand->candidate_datatypes[j]; - /* TODO: I believe the following is wrong! The data types of prev_instruction_type and operand_type DO NOT have to be equal. - * the prev_instruction_type MUST be BOOL compatible. - * I am not too sure about operand_type, does it have to be BOOL compatible, or can it be ANY_BIT compatible? Must check! - */ - if (get_datatype_info_c::is_type_equal(prev_instruction_type,operand_type) && get_datatype_info_c::is_BOOL_compatible(operand_type)) - add_datatype_to_candidate_list(symbol, prev_instruction_type); - } - } - if (debug) std::cout << "S [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; - return NULL; -} - - -void *fill_candidate_datatypes_c::visit(R_operator_c *symbol) { - /* TODO: what if this is a FB call ?? */ - symbol_c *prev_instruction_type, *operand_type; - - if (NULL == prev_il_instruction) return NULL; - for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { - for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { - prev_instruction_type = prev_il_instruction->candidate_datatypes[i]; - operand_type = il_operand->candidate_datatypes[j]; - /* TODO: I believe the following is wrong! The data types of prev_instruction_type and operand_type DO NOT have to be equal. - * the prev_instruction_type MUST be BOOL compatible. - * I am not too sure about operand_type, does it have to be BOOL compatible, or can it be ANY_BIT compatible? Must check! - */ - if (get_datatype_info_c::is_type_equal(prev_instruction_type,operand_type) && get_datatype_info_c::is_BOOL_compatible(operand_type)) - add_datatype_to_candidate_list(symbol, prev_instruction_type); - } - } - if (debug) std::cout << "R [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; - return NULL; -} - - -void *fill_candidate_datatypes_c::visit( S1_operator_c *symbol) {return handle_implicit_il_fb_call(symbol, "S1", symbol->called_fb_declaration);} -void *fill_candidate_datatypes_c::visit( R1_operator_c *symbol) {return handle_implicit_il_fb_call(symbol, "R1", symbol->called_fb_declaration);} +void *fill_candidate_datatypes_c::visit( S_operator_c *symbol) {return handle_S_and_R_operator (symbol, "S", symbol->called_fb_declaration);} +void *fill_candidate_datatypes_c::visit( R_operator_c *symbol) {return handle_S_and_R_operator (symbol, "R", symbol->called_fb_declaration);} + +void *fill_candidate_datatypes_c::visit( S1_operator_c *symbol) {return handle_implicit_il_fb_call(symbol, "S1", symbol->called_fb_declaration);} +void *fill_candidate_datatypes_c::visit( R1_operator_c *symbol) {return handle_implicit_il_fb_call(symbol, "R1", symbol->called_fb_declaration);} void *fill_candidate_datatypes_c::visit( CLK_operator_c *symbol) {return handle_implicit_il_fb_call(symbol, "CLK", symbol->called_fb_declaration);} -void *fill_candidate_datatypes_c::visit( CU_operator_c *symbol) {return handle_implicit_il_fb_call(symbol, "CU", symbol->called_fb_declaration);} -void *fill_candidate_datatypes_c::visit( CD_operator_c *symbol) {return handle_implicit_il_fb_call(symbol, "CD", symbol->called_fb_declaration);} -void *fill_candidate_datatypes_c::visit( PV_operator_c *symbol) {return handle_implicit_il_fb_call(symbol, "PV", symbol->called_fb_declaration);} -void *fill_candidate_datatypes_c::visit( IN_operator_c *symbol) {return handle_implicit_il_fb_call(symbol, "IN", symbol->called_fb_declaration);} -void *fill_candidate_datatypes_c::visit( PT_operator_c *symbol) {return handle_implicit_il_fb_call(symbol, "PT", symbol->called_fb_declaration);} +void *fill_candidate_datatypes_c::visit( CU_operator_c *symbol) {return handle_implicit_il_fb_call(symbol, "CU", symbol->called_fb_declaration);} +void *fill_candidate_datatypes_c::visit( CD_operator_c *symbol) {return handle_implicit_il_fb_call(symbol, "CD", symbol->called_fb_declaration);} +void *fill_candidate_datatypes_c::visit( PV_operator_c *symbol) {return handle_implicit_il_fb_call(symbol, "PV", symbol->called_fb_declaration);} +void *fill_candidate_datatypes_c::visit( IN_operator_c *symbol) {return handle_implicit_il_fb_call(symbol, "IN", symbol->called_fb_declaration);} +void *fill_candidate_datatypes_c::visit( PT_operator_c *symbol) {return handle_implicit_il_fb_call(symbol, "PT", symbol->called_fb_declaration);} void *fill_candidate_datatypes_c::visit( AND_operator_c *symbol) {return handle_binary_operator(widen_AND_table, symbol, prev_il_instruction, il_operand);} void *fill_candidate_datatypes_c::visit( OR_operator_c *symbol) {return handle_binary_operator( widen_OR_table, symbol, prev_il_instruction, il_operand);} @@ -1969,17 +1963,9 @@ /* B 3.2.2 Subprogram Control Statements */ /*****************************************/ void *fill_candidate_datatypes_c::visit(fb_invocation_c *symbol) { - symbol_c *fb_type_id = search_varfb_instance_type->get_basetype_id(symbol->fb_name); - /* Although a call to a non-declared FB is a semantic error, this is currently caught by stage 2! */ - if (NULL == fb_type_id) ERROR; - - function_block_declaration_c *fb_decl = function_block_type_symtable.find_value(fb_type_id); - if (function_block_type_symtable.end_value() == fb_decl) - /* The fb_name not the name of a FB instance. Most probably it is the name of a variable of some other type. */ - fb_decl = NULL; - - /* Although a call to a non-declared FB is a semantic error, this is currently caught by stage 2! */ - if (NULL == fb_decl) ERROR; + symbol_c *fb_decl = search_varfb_instance_type->get_basetype_decl(symbol->fb_name); + if (! get_datatype_info_c::is_function_block(fb_decl )) fb_decl = NULL; + if (NULL == fb_decl) ERROR; /* Although a call to a non-declared FB is a semantic error, this is currently caught by stage 2! */ if (symbol-> formal_param_list != NULL) symbol->formal_param_list->accept(*this); if (symbol->nonformal_param_list != NULL) symbol->nonformal_param_list->accept(*this); diff -r 27f246b35ac2 -r 783ef40344dd stage3/fill_candidate_datatypes.hh --- a/stage3/fill_candidate_datatypes.hh Tue Aug 20 11:11:09 2013 +0100 +++ b/stage3/fill_candidate_datatypes.hh Tue Aug 20 11:15:40 2013 +0100 @@ -89,7 +89,8 @@ bool match_nonformal_call(symbol_c *f_call, symbol_c *f_decl); bool match_formal_call (symbol_c *f_call, symbol_c *f_decl, symbol_c **first_param_datatype = NULL); void handle_function_call(symbol_c *fcall, generic_function_call_t fcall_data); - void *handle_implicit_il_fb_call(symbol_c *il_instruction, const char *param_name, symbol_c *&called_fb_declaration); + void *handle_implicit_il_fb_call(symbol_c *il_instruction, const char *param_name, symbol_c *&called_fb_declaration); + void *handle_S_and_R_operator (symbol_c *symbol, const char *operator_str, symbol_c *&called_fb_declaration); void *handle_equality_comparison(const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr); void *handle_binary_expression (const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr); void *handle_binary_operator (const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr); diff -r 27f246b35ac2 -r 783ef40344dd stage3/narrow_candidate_datatypes.cc --- a/stage3/narrow_candidate_datatypes.cc Tue Aug 20 11:11:09 2013 +0100 +++ b/stage3/narrow_candidate_datatypes.cc Tue Aug 20 11:15:40 2013 +0100 @@ -322,11 +322,9 @@ /* set the datatype of the il_operand, this is, the FB being called! */ if (NULL != il_operand) { - /* only set it if it is in the candidate datatypes list! */ - set_datatype(called_fb_declaration, il_operand); + set_datatype(called_fb_declaration, il_operand); /* only set it if it is in the candidate datatypes list! */ il_operand->accept(*this); } - symbol_c *fb_decl = il_operand->datatype; if (0 == fake_prev_il_instruction->prev_il_instruction.size()) { /* This IL implicit FB call (e.g. CLK ton_var) is not preceded by another IL instruction @@ -336,8 +334,10 @@ return NULL; } + symbol_c *fb_decl = (NULL == il_operand)? NULL : il_operand->datatype; + if (NULL == fb_decl) { - /* the il_operand is a not FB instance */ + /* the il_operand is a not FB instance, or it simply does not even exist, */ /* so we simply pass on the required datatype to the prev_il_instructions */ /* The invalid FB invocation will be caught in the print_datatypes_error_c by analysing NULL value in il_operand->datatype! */ set_datatype_in_prev_il_instructions(il_instruction->datatype, fake_prev_il_instruction); @@ -999,7 +999,7 @@ * | il_call_operator prev_declared_fb_name '(' il_operand_list ')' * | il_call_operator prev_declared_fb_name '(' eol_list il_param_list ')' */ -/* NOTE: The parameter 'called_fb_declaration'is used to pass data between stage 3 and stage4 (although currently it is not used in stage 4 */ +/* NOTE: The parameter 'called_fb_declaration'is used to pass data between stage 3 and stage4 */ // SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list, symbol_c *called_fb_declaration) void *narrow_candidate_datatypes_c::visit(il_fb_call_c *symbol) { symbol_c *fb_decl = symbol->called_fb_declaration; @@ -1093,7 +1093,9 @@ if (NULL != deprecated_operation) *deprecated_operation = false; - /* NOTE 1: the il_operand __may__ be pointing to a parenthesized list of IL instructions. + if (NULL == il_operand) return NULL; /* if no IL operand => error in the source code!! */ + + /* NOTE 1: the il_operand __may__ be pointing to a parenthesized list of IL instructions. * e.g. LD 33 * AND ( 45 * OR 56 @@ -1136,9 +1138,8 @@ void *narrow_candidate_datatypes_c::handle_il_instruction(symbol_c *symbol) { - if (NULL == symbol->datatype) - /* next IL instructions were unable to determine the datatype this instruction should produce */ - return NULL; + if (NULL == symbol->datatype) return NULL; /* next IL instructions were unable to determine the datatype this instruction should produce */ + /* NOTE 1: the il_operand __may__ be pointing to a parenthesized list of IL instructions. * e.g. LD 33 * AND ( 45 @@ -1158,6 +1159,7 @@ set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction); /* set the datatype for the operand */ + if (NULL == il_operand) return NULL; /* if no IL operand => error in the source code!! */ il_operand->datatype = symbol->datatype; il_operand->accept(*this); return NULL; @@ -1167,10 +1169,10 @@ void *narrow_candidate_datatypes_c::visit(LD_operator_c *symbol) { - if (NULL == symbol->datatype) - /* next IL instructions were unable to determine the datatype this instruction should produce */ - return NULL; + if (NULL == symbol->datatype) return NULL; /* next IL instructions were unable to determine the datatype this instruction should produce */ + /* set the datatype for the operand */ + if (NULL == il_operand) return NULL; /* if no IL operand => error in the source code!! */ il_operand->datatype = symbol->datatype; il_operand->accept(*this); return NULL; @@ -1178,10 +1180,10 @@ void *narrow_candidate_datatypes_c::visit(LDN_operator_c *symbol) { - if (NULL == symbol->datatype) - /* next IL instructions were unable to determine the datatype this instruction should produce */ - return NULL; + if (NULL == symbol->datatype) return NULL; /* next IL instructions were unable to determine the datatype this instruction should produce */ + /* set the datatype for the operand */ + if (NULL == il_operand) return NULL; /* if no IL operand => error in the source code!! */ il_operand->datatype = symbol->datatype; il_operand->accept(*this); return NULL; @@ -1190,28 +1192,39 @@ void *narrow_candidate_datatypes_c::visit(ST_operator_c *symbol) { if (symbol->candidate_datatypes.size() != 1) return NULL; + symbol->datatype = symbol->candidate_datatypes[0]; - /* set the datatype for the operand */ - il_operand->datatype = symbol->datatype; - il_operand->accept(*this); /* set the desired datatype of the previous il instruction */ set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction); /* In the case of the ST operator, we must set the datatype of the il_instruction_c object that points to this ST_operator_c ourselves, * since the following il_instruction_c objects have not done it, as is normal/standard for other instructions! */ current_il_instruction->datatype = symbol->datatype; + + /* set the datatype for the operand */ + if (NULL == il_operand) return NULL; /* if no IL operand => error in the source code!! */ + il_operand->datatype = symbol->datatype; + il_operand->accept(*this); + return NULL; } void *narrow_candidate_datatypes_c::visit(STN_operator_c *symbol) { if (symbol->candidate_datatypes.size() != 1) return NULL; + symbol->datatype = symbol->candidate_datatypes[0]; + /* set the desired datatype of the previous il instruction */ + set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction); + /* In the case of the ST operator, we must set the datatype of the il_instruction_c object that points to this ST_operator_c ourselves, + * since the following il_instruction_c objects have not done it, as is normal/standard for other instructions! + */ + current_il_instruction->datatype = symbol->datatype; + /* set the datatype for the operand */ + if (NULL == il_operand) return NULL; /* if no IL operand => error in the source code!! */ il_operand->datatype = symbol->datatype; il_operand->accept(*this); - /* set the desired datatype of the previous il instruction */ - set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction); return NULL; } @@ -1220,22 +1233,23 @@ * NOT [] * However, it does not define the semantic of the NOT operation when the is specified. * We therefore consider it an error if an il_operand is specified! - */ - /* We do not change the data type, we simply invert the bits in bit types! */ + * This error will be detected in print_datatypes_error_c!! + */ + /* This operator does not change the data type, it simply inverts the bits in the ANT_BIT data types! */ /* So, we set the desired datatype of the previous il instruction */ set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction); return NULL; } void *narrow_candidate_datatypes_c::visit(S_operator_c *symbol) { - /* TODO: what if this is a FB call? */ - return handle_il_instruction(symbol); -} + if (NULL != symbol->called_fb_declaration) /* FB call semantics */ return narrow_implicit_il_fb_call(symbol, "S", symbol->called_fb_declaration); + else /* Reset semantics */ return handle_il_instruction(symbol); +} + void *narrow_candidate_datatypes_c::visit(R_operator_c *symbol) { - /* TODO: what if this is a FB call? */ - return handle_il_instruction(symbol); -} - + if (NULL != symbol->called_fb_declaration) /* FB call semantics */ return narrow_implicit_il_fb_call(symbol, "R", symbol->called_fb_declaration); + else /* Reset semantics */ return handle_il_instruction(symbol); +} void *narrow_candidate_datatypes_c::visit( S1_operator_c *symbol) {return narrow_implicit_il_fb_call(symbol, "S1", symbol->called_fb_declaration);} void *narrow_candidate_datatypes_c::visit( R1_operator_c *symbol) {return narrow_implicit_il_fb_call(symbol, "R1", symbol->called_fb_declaration);} diff -r 27f246b35ac2 -r 783ef40344dd stage3/print_datatypes_error.cc --- a/stage3/print_datatypes_error.cc Tue Aug 20 11:11:09 2013 +0100 +++ b/stage3/print_datatypes_error.cc Tue Aug 20 11:15:40 2013 +0100 @@ -278,7 +278,7 @@ STAGE3_ERROR(0, il_operator, il_operator, "Missing operand for FB call operator '%s'.", param_name); return NULL; } - il_operand->accept(*this); + // il_operand->accept(*this); // NOT required. The il_simple_operation_c already visits it!! if (NULL == called_fb_declaration) { STAGE3_ERROR(0, il_operator, il_operand, "Invalid FB call: operand is not a FB instance."); @@ -760,10 +760,8 @@ void *print_datatypes_error_c::visit(il_simple_operation_c *symbol) { il_operand = symbol->il_operand; - if (NULL != symbol->il_operand) { - symbol->il_operand->accept(*this); - } - /* recursive call to see whether data types are compatible */ + if (NULL != il_operand) symbol->il_operand->accept(*this); /* recursive call to see whether data types are compatible */ + symbol->il_simple_operator->accept(*this); il_operand = NULL; return NULL; @@ -932,50 +930,22 @@ /* B 2.2 Operators */ /*******************/ void *print_datatypes_error_c::print_binary_operator_errors(const char *il_operator, symbol_c *symbol, bool deprecated_operation) { - if ((symbol->candidate_datatypes.size() == 0) && (il_operand->candidate_datatypes.size() > 0)) { - STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for '%s' operator.", il_operator); - } else if (NULL == symbol->datatype) { - STAGE3_WARNING(symbol, symbol, "Result of '%s' operation is never used.", il_operator); + if (NULL == il_operand) { + STAGE3_ERROR(0, symbol, symbol, "Missing operand for %s operator.", il_operator); // message (a) + } else if ((symbol->candidate_datatypes.size() == 0) && (il_operand->candidate_datatypes.size() > 0)) { + STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for '%s' operator.", il_operator); // message (b) + } else if (NULL == symbol->datatype) { + STAGE3_WARNING(symbol, symbol, "Result of '%s' operation is never used.", il_operator); // message (c) } else if (deprecated_operation) - STAGE3_WARNING(symbol, symbol, "Deprecated operation for '%s' operator.", il_operator); - return NULL; -} - - -void *print_datatypes_error_c::visit(LD_operator_c *symbol) { - return NULL; -} - -void *print_datatypes_error_c::visit(LDN_operator_c *symbol) { - if ((symbol->candidate_datatypes.size() == 0) && - (il_operand->candidate_datatypes.size() > 0)) - STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for 'LDN' operator."); - return NULL; -} - -void *print_datatypes_error_c::visit(ST_operator_c *symbol) { - /* MANU: - * if prev_instruction is NULL we can print a message error or warning error like: - * we can't use a ST like first instruction. - * What do you think? - */ - if ((symbol->candidate_datatypes.size() == 0) && - (il_operand->candidate_datatypes.size() > 0)) - STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for 'ST' operator."); - return NULL; -} - -void *print_datatypes_error_c::visit(STN_operator_c *symbol) { - /* MANU: - * if prev_instruction is NULL we can print a message error or warning error like: - * we can't use a ST like first instruction. - * What do you think? - */ - if ((symbol->candidate_datatypes.size() == 0) && - (il_operand->candidate_datatypes.size() > 0)) - STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for 'STN' operator."); - return NULL; -} + STAGE3_WARNING(symbol, symbol, "Deprecated operation for '%s' operator.", il_operator); // message (d) + return NULL; +} + + +void *print_datatypes_error_c::visit( LD_operator_c *symbol) {return print_binary_operator_errors("LD" , symbol);} // I believe it will never emit messages (b) and (c)!! +void *print_datatypes_error_c::visit( LDN_operator_c *symbol) {return print_binary_operator_errors("LDN" , symbol);} // I believe it will never emit message (c) +void *print_datatypes_error_c::visit( ST_operator_c *symbol) {return print_binary_operator_errors("ST" , symbol);} // I believe it will never emit message (c) +void *print_datatypes_error_c::visit( STN_operator_c *symbol) {return print_binary_operator_errors("STN" , symbol);} // I believe it will never emit message (c) void *print_datatypes_error_c::visit(NOT_operator_c *symbol) { /* NOTE: the standard allows syntax in which the NOT operator is followed by an optional @@ -983,27 +953,21 @@ * However, it does not define the semantic of the NOT operation when the is specified. * We therefore consider it an error if an il_operand is specified! */ - if (il_operand != NULL) + if (il_operand != NULL) { STAGE3_ERROR(0, symbol, symbol, "'NOT' operator may not have an operand."); - if (symbol->candidate_datatypes.size() == 0) + } else if (symbol->candidate_datatypes.size() == 0) STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for 'NOT' operator."); return NULL; } void *print_datatypes_error_c::visit(S_operator_c *symbol) { - /* TODO: what if this is a FB call ?? */ - if ((symbol->candidate_datatypes.size() == 0) && - (il_operand->candidate_datatypes.size() > 0)) - STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for 'S' operator."); - return NULL; + if (NULL != symbol->called_fb_declaration) /* FB call semantics */ return handle_implicit_il_fb_invocation("S", symbol, symbol->called_fb_declaration); + else /* Reset semantics */ return print_binary_operator_errors ("S", symbol); } void *print_datatypes_error_c::visit(R_operator_c *symbol) { - /* TODO: what if this is a FB call ?? */ - if ((symbol->candidate_datatypes.size() == 0) && - (il_operand->candidate_datatypes.size() > 0)) - STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for 'R' operator."); - return NULL; + if (NULL != symbol->called_fb_declaration) /* FB call semantics */ return handle_implicit_il_fb_invocation("R", symbol, symbol->called_fb_declaration); + else /* Reset semantics */ return print_binary_operator_errors ("R", symbol); } void *print_datatypes_error_c::visit( S1_operator_c *symbol) {return handle_implicit_il_fb_invocation( "S1", symbol, symbol->called_fb_declaration);} diff -r 27f246b35ac2 -r 783ef40344dd stage4/generate_c/generate_c_il.cc --- a/stage4/generate_c/generate_c_il.cc Tue Aug 20 11:11:09 2013 +0100 +++ b/stage4/generate_c/generate_c_il.cc Tue Aug 20 11:15:40 2013 +0100 @@ -1530,6 +1530,16 @@ void *visit(S_operator_c *symbol) { + /* This operator must implement one of two possible semantics: + * - FB call + * - Set all the bits of an ANY_BIT type variable to 1 + */ + + /* Check whether we must implement the FB call semantics... */ + if (NULL != symbol->called_fb_declaration) + return XXX_CAL_operator( "S", this->current_operand); + + /* Implement the bit setting semantics... */ if (wanted_variablegeneration != expression_vg) { s4o.print("LD"); return NULL; @@ -1552,6 +1562,16 @@ void *visit(R_operator_c *symbol) { + /* This operator must implement one of two possible semantics: + * - FB call + * - Set all the bits of an ANY_BIT type variable to 0 + */ + + /* Check whether we must implement the FB call semantics... */ + if (NULL != symbol->called_fb_declaration) + return XXX_CAL_operator( "R", this->current_operand); + + /* Implement the bit setting semantics... */ if (wanted_variablegeneration != expression_vg) { s4o.print("LD"); return NULL;