# HG changeset patch # User mjsousa # Date 1377097730 -3600 # Node ID 149398f525a7ff6c1aa3a2dc605c2b059f1b4d04 # Parent 182036ed647533e27c3016438a4dff7d37676d9b make sure all IL operands are narrowed (datatype checking algorithm) diff -r 182036ed6475 -r 149398f525a7 stage3/narrow_candidate_datatypes.cc --- a/stage3/narrow_candidate_datatypes.cc Wed Aug 21 16:06:43 2013 +0100 +++ b/stage3/narrow_candidate_datatypes.cc Wed Aug 21 16:08:50 2013 +0100 @@ -1082,14 +1082,59 @@ /*******************/ /* B 2.2 Operators */ /*******************/ +/* Sets the datatype of the il_operand, and calls it recursively! + * + * NOTE 1: the il_operand __may__ be pointing to a parenthesized list of IL instructions. + * e.g. LD 33 + * AND ( 45 + * OR 56 + * ) + * When we handle the first 'AND' IL_operator, the il_operand will point to an simple_instr_list_c. + * In this case, when we call il_operand->accept(*this);, the prev_il_instruction pointer will be overwritten! + * + * So, if yoy wish to set the prev_il_instruction->datatype = symbol->datatype; + * do it __before__ calling set_il_operand_datatype() (which in turn calls il_operand->accept(*this)) !! + */ +void *narrow_candidate_datatypes_c::set_il_operand_datatype(symbol_c *il_operand, symbol_c *datatype) { + if (NULL == il_operand) return NULL; /* if no IL operand => error in the source code!! */ + + /* If il_operand already has a non-NULL datatype (remember, narrow algorithm runs twice over IL lists!), + * 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 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; + /* OK, so both the datatypes are valid, but are they equal? */ + 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; + } + + /* Set the il_operand's datatype. Note that the new 'datatype' may even be NULL!!! */ + il_operand->datatype = datatype; + /* Even if we are not able to determine the il_operand's datatype ('datatype' is NULL), we still visit it recursively, + * to give a chance of any complex expressions embedded in the il_operand (e.g. expressions inside array subscripts!) + * to be narrowed too. + */ + il_operand->accept(*this); + return NULL; +} + + + + void *narrow_candidate_datatypes_c::narrow_binary_operator(const struct widen_entry widen_table[], symbol_c *symbol, bool *deprecated_operation) { symbol_c *prev_instruction_type, *operand_type; int count = 0; - if (NULL == symbol->datatype) - /* next IL instructions were unable to determine the datatype this instruction should produce */ - return NULL; - if (NULL != deprecated_operation) *deprecated_operation = false; @@ -1110,26 +1155,29 @@ * 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. */ - for(unsigned int i = 0; i < fake_prev_il_instruction->candidate_datatypes.size(); i++) { - for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { - prev_instruction_type = fake_prev_il_instruction->candidate_datatypes[i]; - operand_type = il_operand->candidate_datatypes[j]; - if (is_widening_compatible(widen_table, prev_instruction_type, operand_type, symbol->datatype, deprecated_operation)) { - /* set the desired datatype of the previous il instruction */ - set_datatype_in_prev_il_instructions(prev_instruction_type, fake_prev_il_instruction); - /* set the datatype for the operand */ - il_operand->datatype = operand_type; - il_operand->accept(*this); - - /* NOTE: DO NOT search any further! Return immediately! - * Since we support SAFE*** datatypes, multiple entries in the widen_table may be compatible. - * If we try to set more than one distinct datatype on the same symbol, then the datatype will be set to - * an invalid_datatype, which is NOT what we want! - */ - return NULL; + if (NULL != symbol->datatype) { // next IL instructions were able to determine the datatype this instruction should produce + for(unsigned int i = 0; i < fake_prev_il_instruction->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { + prev_instruction_type = fake_prev_il_instruction->candidate_datatypes[i]; + operand_type = il_operand->candidate_datatypes[j]; + if (is_widening_compatible(widen_table, prev_instruction_type, operand_type, symbol->datatype, deprecated_operation)) { + /* set the desired datatype of the previous il instruction */ + set_datatype_in_prev_il_instructions(prev_instruction_type, fake_prev_il_instruction); + /* set the datatype for the operand */ + set_il_operand_datatype(il_operand, operand_type); + + /* NOTE: DO NOT search any further! Return immediately! + * Since we support SAFE*** datatypes, multiple entries in the widen_table may be compatible. + * If we try to set more than one distinct datatype on the same symbol, then the datatype will be set to + * an invalid_datatype, which is NOT what we want! + */ + return NULL; + } } } } + /* We were not able to determine the required datatype, but we still give the il_operand a chance to be narrowed! */ + set_il_operand_datatype(il_operand, NULL); return NULL; } @@ -1138,93 +1186,55 @@ void *narrow_candidate_datatypes_c::handle_il_instruction(symbol_c *symbol) { - 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 - * OR 56 - * ) - * When we handle the first 'AND' IL_operator, the il_operand will point to an simple_instr_list_c. - * In this case, when we call il_operand->accept(*this);, the prev_il_instruction pointer will be overwritten! - * - * We must therefore set the prev_il_instruction->datatype = symbol->datatype; - * __before__ calling il_operand->accept(*this) !! - * + /* * 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. */ - /* set the desired datatype of the previous il instruction */ - set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction); - + 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 */ - 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(LD_operator_c *symbol) { - 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; -} - - -void *narrow_candidate_datatypes_c::visit(LDN_operator_c *symbol) { - 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; -} + set_il_operand_datatype(il_operand, symbol->datatype); + return NULL; +} + + + + +void *narrow_candidate_datatypes_c::visit( LD_operator_c *symbol) {return set_il_operand_datatype(il_operand, symbol->datatype);} +void *narrow_candidate_datatypes_c::visit(LDN_operator_c *symbol) {return set_il_operand_datatype(il_operand, symbol->datatype);} 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 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; + if (symbol->candidate_datatypes.size() == 1) { + 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_il_operand_datatype(il_operand, symbol->datatype); return NULL; } void *narrow_candidate_datatypes_c::visit(STN_operator_c *symbol) { - if (symbol->candidate_datatypes.size() != 1) - return NULL; + if (symbol->candidate_datatypes.size() == 1) { + 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; + } - 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_il_operand_datatype(il_operand, symbol->datatype); return NULL; } diff -r 182036ed6475 -r 149398f525a7 stage3/narrow_candidate_datatypes.hh --- a/stage3/narrow_candidate_datatypes.hh Wed Aug 21 16:06:43 2013 +0100 +++ b/stage3/narrow_candidate_datatypes.hh Wed Aug 21 16:08:50 2013 +0100 @@ -72,11 +72,12 @@ 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_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 *handle_il_instruction(symbol_c *symbol); + void *set_il_operand_datatype (symbol_c *il_operand, symbol_c *datatype); + void *handle_il_instruction (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);