# HG changeset patch # User mjsousa # Date 1377116815 -3600 # Node ID 13ea7c08001814f13812bf8249646195ce7a1e88 # Parent e0184feaebd2420221e988f1bb32a9298b863378 Fix datatype analysis of conditional IL operators (CALC, CALCN, RETC, RETCN, JMPC, JMPCN, S and R) diff -r e0184feaebd2 -r 13ea7c080018 stage3/narrow_candidate_datatypes.cc --- a/stage3/narrow_candidate_datatypes.cc Wed Aug 21 21:14:50 2013 +0100 +++ b/stage3/narrow_candidate_datatypes.cc Wed Aug 21 21:26:55 2013 +0100 @@ -1102,18 +1102,19 @@ * but narrow algorithm has not yet been able to determine what datatype it should take? This is strange, * and most probably an error! */ - if ((NULL != il_operand->datatype) && (NULL == datatype)) - ERROR; + if ((NULL != il_operand->datatype) && (NULL == datatype)) ERROR; /* If the il_operand's datatype has already been set previously, and * the narrow algorithm has already determined the datatype the il_operand should take! * ...we just make sure that the new datatype is the same as the current il_operand's datatype */ if ((NULL != il_operand->datatype) && (NULL != datatype)) { - /* Only one of the two datatypes is an invalid_type_name_c? This implies they are diferent!! */ - if ((!get_datatype_info_c::is_type_valid(datatype)) ^ ((!get_datatype_info_c::is_type_valid(il_operand->datatype)))) ERROR; + /* Both datatypes are an invalid_type_name_c. This implies they are the same!! */ + if ((!get_datatype_info_c::is_type_valid(datatype)) && ((!get_datatype_info_c::is_type_valid(il_operand->datatype)))) + return NULL;; /* OK, so both the datatypes are valid, but are they equal? */ - if ( !get_datatype_info_c::is_type_equal(il_operand->datatype, datatype)) ERROR; + if ( !get_datatype_info_c::is_type_equal(il_operand->datatype, datatype)) + ERROR; /* The datatypes are the same. We have nothing to do, so we simply return! */ return NULL; } @@ -1184,19 +1185,59 @@ - -void *narrow_candidate_datatypes_c::handle_il_instruction(symbol_c *symbol) { - /* - * NOTE 2: We do not need to call prev_il_instruction->accept(*this), as the object to which prev_il_instruction - * is pointing to will be later narrowed by the call from the for() loop of the instruction_list_c - * (or simple_instr_list_c), which iterates backwards. - */ - if (NULL != symbol->datatype) // next IL instructions were able to determine the datatype this instruction should produce - /* set the desired datatype of the previous il instruction */ - set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction); - - /* set the datatype for the operand */ - set_il_operand_datatype(il_operand, symbol->datatype); +/* Narrow IL operators whose execution is conditional on the boolean value in the accumulator. + * Basically, narrow the JMPC, JMPCN, RETC, RETCN, CALC, and CALCN operators! + * Also does part of the S and R operator narrowing!!! + */ +void *narrow_candidate_datatypes_c::narrow_conditional_operator(symbol_c *symbol) { + /* if the next IL instructions needs us to provide a datatype other than a BOOL or a SAFEBOOL, + * then we have an internal compiler error - most likely in fill_candidate_datatypes_c + */ + // I (mario) am confident the fill/narrow algorithms are working correctly, so for now we can disable the assertions! + //if ((NULL != symbol->datatype) && (!get_datatype_info_c::is_BOOL_compatible(symbol->datatype))) ERROR; + //if (symbol->candidate_datatypes.size() > 2) ERROR; /* may contain, at most, a BOOL and a SAFEBOOL */ + + /* NOTE: If there is no IL instruction following this S, R, CALC, CALCN, JMPC, JMPCN, RETC, or RETCN instruction, + * we must still provide a bool_type_name_c datatype (if possible, i.e. if it exists in the candidate datatype list). + * If it is not possible, we set it to NULL + * + * NOTE: Note that this algorithm we are implementing is slightly wrong. + * (a) It ignores that a SAFEBOOL may be needed instead of a BOOL datatype. + * (b) It also ignores that this method gets to be called twice on the same + * object (the narrow algorithm runs through the IL list twice in order to + * handle forward JMPs), so the assumption that we must immediately set our + * own datatype if we get called with a NULL symbol->datatype is incorrect + * (it may be that the second time it is called it will be with the correct datatype!). + * + * These two issues (a) and (b) together means that we should only really be setting our own + * datatype if we are certain that the following IL instructions will never set it for us + * - basically if the following IL instruction is a LD, or a JMP to a LD, or a JMP to a JMP to a LD, + * etc..., or a conditional JMP whose both branches go to LD, etc...!!! + * + * At the moment, it seems to me that we would need to write a visitor class to do this for us! + * I currently have other things on my mind at the moment, so I will leave this for later... + * For the moment we just set it to BOOL, and ignore the support of SAFEBOOL! + */ + if (NULL == symbol->datatype) set_datatype(&get_datatype_info_c::bool_type_name /* datatype*/, symbol /* symbol */); + if (NULL == symbol->datatype) ERROR; // the BOOL is not on the candidate_datatypes! Strange... Probably a bug in fill_candidate_datatype_c + + /* set the required datatype of the previous IL instruction, i.e. a bool_type_name_c! */ + set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction); + return NULL; +} + + + +void *narrow_candidate_datatypes_c::narrow_S_and_R_operator(symbol_c *symbol, const char *param_name, symbol_c *called_fb_declaration) { + if (NULL != called_fb_declaration) + /* FB call semantics */ + return narrow_implicit_il_fb_call(symbol, param_name, called_fb_declaration); + + /* Set/Reset semantics */ + narrow_conditional_operator(symbol); + /* set the datatype for the il_operand */ + if ((NULL != il_operand) && (il_operand->candidate_datatypes.size() > 0)) + set_il_operand_datatype(il_operand, il_operand->candidate_datatypes[0]); return NULL; } @@ -1238,28 +1279,20 @@ return NULL; } -void *narrow_candidate_datatypes_c::visit(NOT_operator_c *symbol) { - /* NOTE: the standard allows syntax in which the NOT operator is followed by an optional - * 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! - * 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) { - 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) { - 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); -} + + +/* NOTE: the standard allows syntax in which the NOT operator is followed by an optional + * 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! + * 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 merely set the desired datatype of the previous il instruction */ +void *narrow_candidate_datatypes_c::visit( NOT_operator_c *symbol) {set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);return NULL;} + +void *narrow_candidate_datatypes_c::visit( S_operator_c *symbol) {return narrow_S_and_R_operator (symbol, "S", symbol->called_fb_declaration);} +void *narrow_candidate_datatypes_c::visit( R_operator_c *symbol) {return narrow_S_and_R_operator (symbol, "R", symbol->called_fb_declaration);} 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);} @@ -1289,44 +1322,17 @@ void *narrow_candidate_datatypes_c::visit( NE_operator_c *symbol) {return narrow_binary_operator(widen_CMP_table, symbol);} - - -void *narrow_candidate_datatypes_c::narrow_conditional_flow_control_IL_instruction(symbol_c *symbol) { - /* if the next IL instructions needs us to provide a datatype other than a bool, - * then we have an internal compiler error - most likely in fill_candidate_datatypes_c - */ - if ((NULL != symbol->datatype) && (!get_datatype_info_c::is_BOOL_compatible(symbol->datatype))) ERROR; - if (symbol->candidate_datatypes.size() > 1) ERROR; - - /* NOTE: If there is no IL instruction following this CALC, CALCN, JMPC, JMPC, ..., instruction, - * we must still provide a bool_type_name_c datatype (if possible, i.e. if it exists in the candidate datatype list). - * If it is not possible, we set it to NULL - */ - if (symbol->candidate_datatypes.size() == 0) symbol->datatype = NULL; - else symbol->datatype = symbol->candidate_datatypes[0]; /* i.e. a bool_type_name_c! */ - if ((NULL != symbol->datatype) && (!get_datatype_info_c::is_BOOL_compatible(symbol->datatype))) ERROR; - - /* set the required datatype of the previous IL instruction, i.e. a bool_type_name_c! */ - set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction); - return NULL; -} - - -// SYM_REF0(CAL_operator_c) -// SYM_REF0(CALC_operator_c) -// SYM_REF0(CALCN_operator_c) -/* called from visit(il_fb_call_c *) {symbol->il_call_operator->accpet(*this)} */ +/* visitors to CAL_operator_c, CALC_operator_c and CALCN_operator_c are called from visit(il_fb_call_c *) {symbol->il_call_operator->accept(*this)} */ /* NOTE: The CAL, JMP and RET instructions simply set the desired datatype of the previous il instruction since they do not change the value in the current/default IL variable */ -/* called from il_fb_call_c (symbol->il_call_operator->accpet(*this) ) */ void *narrow_candidate_datatypes_c::visit( CAL_operator_c *symbol) {set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction); return NULL;} void *narrow_candidate_datatypes_c::visit( RET_operator_c *symbol) {set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction); return NULL;} void *narrow_candidate_datatypes_c::visit( JMP_operator_c *symbol) {set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction); return NULL;} -void *narrow_candidate_datatypes_c::visit( CALC_operator_c *symbol) {return narrow_conditional_flow_control_IL_instruction(symbol);} -void *narrow_candidate_datatypes_c::visit(CALCN_operator_c *symbol) {return narrow_conditional_flow_control_IL_instruction(symbol);} -void *narrow_candidate_datatypes_c::visit( RETC_operator_c *symbol) {return narrow_conditional_flow_control_IL_instruction(symbol);} -void *narrow_candidate_datatypes_c::visit(RETCN_operator_c *symbol) {return narrow_conditional_flow_control_IL_instruction(symbol);} -void *narrow_candidate_datatypes_c::visit( JMPC_operator_c *symbol) {return narrow_conditional_flow_control_IL_instruction(symbol);} -void *narrow_candidate_datatypes_c::visit(JMPCN_operator_c *symbol) {return narrow_conditional_flow_control_IL_instruction(symbol);} +void *narrow_candidate_datatypes_c::visit( CALC_operator_c *symbol) {return narrow_conditional_operator(symbol);} +void *narrow_candidate_datatypes_c::visit(CALCN_operator_c *symbol) {return narrow_conditional_operator(symbol);} +void *narrow_candidate_datatypes_c::visit( RETC_operator_c *symbol) {return narrow_conditional_operator(symbol);} +void *narrow_candidate_datatypes_c::visit(RETCN_operator_c *symbol) {return narrow_conditional_operator(symbol);} +void *narrow_candidate_datatypes_c::visit( JMPC_operator_c *symbol) {return narrow_conditional_operator(symbol);} +void *narrow_candidate_datatypes_c::visit(JMPCN_operator_c *symbol) {return narrow_conditional_operator(symbol);} /* Symbol class handled together with function call checks */ // void *visit(il_assign_operator_c *symbol, variable_name); diff -r e0184feaebd2 -r 13ea7c080018 stage3/narrow_candidate_datatypes.hh --- a/stage3/narrow_candidate_datatypes.hh Wed Aug 21 21:14:50 2013 +0100 +++ b/stage3/narrow_candidate_datatypes.hh Wed Aug 21 21:26:55 2013 +0100 @@ -71,21 +71,20 @@ bool is_widening_compatible(const struct widen_entry widen_table[], symbol_c *left_type, symbol_c *right_type, symbol_c *result_type, bool *deprecated_status = NULL); - void narrow_function_invocation(symbol_c *f_call, generic_function_call_t fcall_data); - void narrow_nonformal_call (symbol_c *f_call, symbol_c *f_decl, int *ext_parm_count = NULL); - void narrow_formal_call (symbol_c *f_call, symbol_c *f_decl, int *ext_parm_count = NULL); - void *narrow_implicit_il_fb_call(symbol_c *il_instruction, const char *param_name, symbol_c *&called_fb_declaration); - - void *set_il_operand_datatype (symbol_c *il_operand, symbol_c *datatype); - void *handle_il_instruction (symbol_c *symbol); + void *narrow_spec_init (symbol_c *symbol, symbol_c *type_decl, symbol_c *init_value); + void *narrow_type_decl (symbol_c *symbol, symbol_c *type_name, symbol_c *spec_init); + void narrow_function_invocation (symbol_c *f_call, generic_function_call_t fcall_data); + void narrow_nonformal_call (symbol_c *f_call, symbol_c *f_decl, int *ext_parm_count = NULL); + void narrow_formal_call (symbol_c *f_call, symbol_c *f_decl, int *ext_parm_count = NULL); + void *narrow_implicit_il_fb_call (symbol_c *symbol, const char *param_name, symbol_c *&called_fb_declaration); + void *narrow_S_and_R_operator (symbol_c *symbol, const char *param_name, symbol_c * called_fb_declaration); + void *narrow_conditional_operator(symbol_c *symbol); void *narrow_binary_operator (const struct widen_entry widen_table[], symbol_c *symbol, bool *deprecated_operation = NULL); void *narrow_binary_expression (const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr, bool *deprecated_operation = NULL, bool allow_enums = false); void *narrow_equality_comparison(const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr, bool *deprecated_operation = NULL); - void *narrow_spec_init(symbol_c *symbol, symbol_c *type_decl, symbol_c *init_value); - void *narrow_type_decl(symbol_c *symbol, symbol_c *type_name, symbol_c *spec_init); - - void *narrow_conditional_flow_control_IL_instruction(symbol_c *symbol); + void *set_il_operand_datatype (symbol_c *il_operand, symbol_c *datatype); + public: